Commit 35ddb06a authored by Linus Torvalds's avatar Linus Torvalds

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
  ...
parents 6aa293d8 d69e1164
...@@ -15,12 +15,15 @@ Required properties: ...@@ -15,12 +15,15 @@ Required properties:
Array of strings. Array of strings.
one of: one of:
- "nvidia,tegra186-hsp" - "nvidia,tegra186-hsp"
- "nvidia,tegra194-hsp", "nvidia,tegra186-hsp"
- reg : Offset and length of the register set for the device. - reg : Offset and length of the register set for the device.
- interrupt-names - interrupt-names
Array of strings. Array of strings.
Contains a list of names for the interrupts described by the interrupt Contains a list of names for the interrupts described by the interrupt
property. May contain the following entries, in any order: property. May contain the following entries, in any order:
- "doorbell" - "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 Users of this binding MUST look up entries in the interrupt property
by name, using this interrupt-names property to do so. by name, using this interrupt-names property to do so.
- interrupts - interrupts
...@@ -29,12 +32,29 @@ Required properties: ...@@ -29,12 +32,29 @@ Required properties:
in a matching order. in a matching order.
- #mbox-cells : Should be 2. - #mbox-cells : Should be 2.
The mbox specifier of the "mboxes" property in the client node should The mbox specifier of the "mboxes" property in the client node should contain
contain two data. The first one should be the HSP type and the second two cells. The first cell determines the HSP type and the second cell is used
one should be the ID that the client is going to use. Those information to identify the mailbox that the client is going to use.
can be found in the following file.
- <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: Example:
......
...@@ -152,7 +152,7 @@ static int mhu_probe(struct amba_device *adev, const struct amba_id *id) ...@@ -152,7 +152,7 @@ static int mhu_probe(struct amba_device *adev, const struct amba_id *id)
amba_set_drvdata(adev, mhu); amba_set_drvdata(adev, mhu);
err = mbox_controller_register(&mhu->mbox); err = devm_mbox_controller_register(dev, &mhu->mbox);
if (err) { if (err) {
dev_err(dev, "Failed to register mailboxes %d\n", err); dev_err(dev, "Failed to register mailboxes %d\n", err);
return err; return err;
...@@ -162,15 +162,6 @@ static int mhu_probe(struct amba_device *adev, const struct amba_id *id) ...@@ -162,15 +162,6 @@ static int mhu_probe(struct amba_device *adev, const struct amba_id *id)
return 0; 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[] = { static struct amba_id mhu_ids[] = {
{ {
.id = 0x1bb098, .id = 0x1bb098,
...@@ -186,7 +177,6 @@ static struct amba_driver arm_mhu_driver = { ...@@ -186,7 +177,6 @@ static struct amba_driver arm_mhu_driver = {
}, },
.id_table = mhu_ids, .id_table = mhu_ids,
.probe = mhu_probe, .probe = mhu_probe,
.remove = mhu_remove,
}; };
module_amba_driver(arm_mhu_driver); module_amba_driver(arm_mhu_driver);
......
...@@ -1665,7 +1665,7 @@ static int flexrm_mbox_probe(struct platform_device *pdev) ...@@ -1665,7 +1665,7 @@ static int flexrm_mbox_probe(struct platform_device *pdev)
mbox->controller.chans[index].con_priv = &mbox->rings[index]; mbox->controller.chans[index].con_priv = &mbox->rings[index];
/* Register mailbox controller */ /* Register mailbox controller */
ret = mbox_controller_register(&mbox->controller); ret = devm_mbox_controller_register(dev, &mbox->controller);
if (ret) if (ret)
goto fail_free_debugfs_root; goto fail_free_debugfs_root;
...@@ -1691,8 +1691,6 @@ static int flexrm_mbox_remove(struct platform_device *pdev) ...@@ -1691,8 +1691,6 @@ static int flexrm_mbox_remove(struct platform_device *pdev)
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct flexrm_mbox *mbox = platform_get_drvdata(pdev); struct flexrm_mbox *mbox = platform_get_drvdata(pdev);
mbox_controller_unregister(&mbox->controller);
debugfs_remove_recursive(mbox->root); debugfs_remove_recursive(mbox->root);
platform_msi_domain_free_irqs(dev); platform_msi_domain_free_irqs(dev);
......
...@@ -1471,7 +1471,7 @@ static int pdc_mb_init(struct pdc_state *pdcs) ...@@ -1471,7 +1471,7 @@ static int pdc_mb_init(struct pdc_state *pdcs)
mbc->chans[chan_index].con_priv = pdcs; mbc->chans[chan_index].con_priv = pdcs;
/* Register mailbox controller */ /* Register mailbox controller */
err = mbox_controller_register(mbc); err = devm_mbox_controller_register(dev, mbc);
if (err) { if (err) {
dev_crit(dev, dev_crit(dev,
"Failed to register PDC mailbox controller. Error %d.", "Failed to register PDC mailbox controller. Error %d.",
...@@ -1641,8 +1641,6 @@ static int pdc_remove(struct platform_device *pdev) ...@@ -1641,8 +1641,6 @@ static int pdc_remove(struct platform_device *pdev)
pdc_hw_disable(pdcs); pdc_hw_disable(pdcs);
mbox_controller_unregister(&pdcs->mbc);
dma_pool_destroy(pdcs->rx_buf_pool); dma_pool_destroy(pdcs->rx_buf_pool);
dma_pool_destroy(pdcs->ring_pool); dma_pool_destroy(pdcs->ring_pool);
return 0; return 0;
......
// SPDX-License-Identifier: GPL-2.0
/* /*
* Copyright (C) 2010,2015 Broadcom * Copyright (C) 2010,2015 Broadcom
* Copyright (C) 2013-2014 Lubomir Rintel * Copyright (C) 2013-2014 Lubomir Rintel
* Copyright (C) 2013 Craig McGeachie * 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: * Parts of the driver are based on:
* - arch/arm/mach-bcm2708/vcio.c file written by Gray Girling that was * - 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/ * 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) ...@@ -178,7 +172,7 @@ static int bcm2835_mbox_probe(struct platform_device *pdev)
if (!mbox->controller.chans) if (!mbox->controller.chans)
return -ENOMEM; return -ENOMEM;
ret = mbox_controller_register(&mbox->controller); ret = devm_mbox_controller_register(dev, &mbox->controller);
if (ret) if (ret)
return ret; return ret;
...@@ -188,13 +182,6 @@ static int bcm2835_mbox_probe(struct platform_device *pdev) ...@@ -188,13 +182,6 @@ static int bcm2835_mbox_probe(struct platform_device *pdev)
return ret; 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[] = { static const struct of_device_id bcm2835_mbox_of_match[] = {
{ .compatible = "brcm,bcm2835-mbox", }, { .compatible = "brcm,bcm2835-mbox", },
{}, {},
...@@ -207,7 +194,6 @@ static struct platform_driver bcm2835_mbox_driver = { ...@@ -207,7 +194,6 @@ static struct platform_driver bcm2835_mbox_driver = {
.of_match_table = bcm2835_mbox_of_match, .of_match_table = bcm2835_mbox_of_match,
}, },
.probe = bcm2835_mbox_probe, .probe = bcm2835_mbox_probe,
.remove = bcm2835_mbox_remove,
}; };
module_platform_driver(bcm2835_mbox_driver); module_platform_driver(bcm2835_mbox_driver);
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#define MBOX_AUTOMATIC_ACK 1 #define MBOX_AUTOMATIC_ACK 1
#define MBOX_STATE_IDLE BIT(4) #define MBOX_STATE_IDLE BIT(4)
#define MBOX_STATE_READY BIT(5)
#define MBOX_STATE_ACK BIT(7) #define MBOX_STATE_ACK BIT(7)
#define MBOX_MSG_LEN 8 #define MBOX_MSG_LEN 8
...@@ -91,8 +92,8 @@ static int hi3660_mbox_check_state(struct mbox_chan *chan) ...@@ -91,8 +92,8 @@ static int hi3660_mbox_check_state(struct mbox_chan *chan)
unsigned long val; unsigned long val;
unsigned int ret; unsigned int ret;
/* Mailbox is idle so directly bail out */ /* Mailbox is ready to use */
if (readl(base + MBOX_MODE_REG) & MBOX_STATE_IDLE) if (readl(base + MBOX_MODE_REG) & MBOX_STATE_READY)
return 0; return 0;
/* Wait for acknowledge from remote */ /* Wait for acknowledge from remote */
...@@ -103,9 +104,9 @@ static int hi3660_mbox_check_state(struct mbox_chan *chan) ...@@ -103,9 +104,9 @@ static int hi3660_mbox_check_state(struct mbox_chan *chan)
return ret; return ret;
} }
/* Ensure channel is released */ /* clear ack state, mailbox will get back to ready state */
writel(0xffffffff, base + MBOX_IMASK_REG); writel(BIT(mchan->ack_irq), base + MBOX_ICLR_REG);
writel(BIT(mchan->ack_irq), base + MBOX_SRC_REG);
return 0; return 0;
} }
...@@ -160,10 +161,6 @@ static int hi3660_mbox_startup(struct mbox_chan *chan) ...@@ -160,10 +161,6 @@ static int hi3660_mbox_startup(struct mbox_chan *chan)
{ {
int ret; int ret;
ret = hi3660_mbox_check_state(chan);
if (ret)
return ret;
ret = hi3660_mbox_unlock(chan); ret = hi3660_mbox_unlock(chan);
if (ret) if (ret)
return ret; return ret;
...@@ -183,10 +180,11 @@ static int hi3660_mbox_send_data(struct mbox_chan *chan, void *msg) ...@@ -183,10 +180,11 @@ static int hi3660_mbox_send_data(struct mbox_chan *chan, void *msg)
void __iomem *base = MBOX_BASE(mbox, ch); void __iomem *base = MBOX_BASE(mbox, ch);
u32 *buf = msg; u32 *buf = msg;
unsigned int i; unsigned int i;
int ret;
/* Ensure channel is released */ ret = hi3660_mbox_check_state(chan);
writel_relaxed(0xffffffff, base + MBOX_IMASK_REG); if (ret)
writel_relaxed(BIT(mchan->ack_irq), base + MBOX_SRC_REG); return ret;
/* Clear mask for destination interrupt */ /* Clear mask for destination interrupt */
writel_relaxed(~BIT(mchan->dst_irq), base + MBOX_IMASK_REG); 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) ...@@ -206,7 +204,7 @@ static int hi3660_mbox_send_data(struct mbox_chan *chan, void *msg)
return 0; return 0;
} }
static struct mbox_chan_ops hi3660_mbox_ops = { static const struct mbox_chan_ops hi3660_mbox_ops = {
.startup = hi3660_mbox_startup, .startup = hi3660_mbox_startup,
.send_data = hi3660_mbox_send_data, .send_data = hi3660_mbox_send_data,
}; };
...@@ -267,7 +265,7 @@ static int hi3660_mbox_probe(struct platform_device *pdev) ...@@ -267,7 +265,7 @@ static int hi3660_mbox_probe(struct platform_device *pdev)
for (ch = 0; ch < MBOX_CHAN_MAX; ch++) for (ch = 0; ch < MBOX_CHAN_MAX; ch++)
chan[ch].con_priv = (void *)ch; chan[ch].con_priv = (void *)ch;
err = mbox_controller_register(&mbox->controller); err = devm_mbox_controller_register(dev, &mbox->controller);
if (err) { if (err) {
dev_err(dev, "Failed to register mailbox %d\n", err); dev_err(dev, "Failed to register mailbox %d\n", err);
return err; return err;
...@@ -278,17 +276,8 @@ static int hi3660_mbox_probe(struct platform_device *pdev) ...@@ -278,17 +276,8 @@ static int hi3660_mbox_probe(struct platform_device *pdev)
return 0; 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 = { static struct platform_driver hi3660_mbox_driver = {
.probe = hi3660_mbox_probe, .probe = hi3660_mbox_probe,
.remove = hi3660_mbox_remove,
.driver = { .driver = {
.name = "hi3660-mbox", .name = "hi3660-mbox",
.of_match_table = hi3660_mbox_of_match, .of_match_table = hi3660_mbox_of_match,
......
...@@ -349,7 +349,7 @@ static int hi6220_mbox_probe(struct platform_device *pdev) ...@@ -349,7 +349,7 @@ static int hi6220_mbox_probe(struct platform_device *pdev)
mbox->controller.txpoll_period = 5; mbox->controller.txpoll_period = 5;
} }
err = mbox_controller_register(&mbox->controller); err = devm_mbox_controller_register(dev, &mbox->controller);
if (err) { if (err) {
dev_err(dev, "Failed to register mailbox %d\n", err); dev_err(dev, "Failed to register mailbox %d\n", err);
return err; return err;
...@@ -360,14 +360,6 @@ static int hi6220_mbox_probe(struct platform_device *pdev) ...@@ -360,14 +360,6 @@ static int hi6220_mbox_probe(struct platform_device *pdev)
return 0; 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 = { static struct platform_driver hi6220_mbox_driver = {
.driver = { .driver = {
.name = "hi6220-mbox", .name = "hi6220-mbox",
...@@ -375,7 +367,6 @@ static struct platform_driver hi6220_mbox_driver = { ...@@ -375,7 +367,6 @@ static struct platform_driver hi6220_mbox_driver = {
.of_match_table = hi6220_mbox_of_match, .of_match_table = hi6220_mbox_of_match,
}, },
.probe = hi6220_mbox_probe, .probe = hi6220_mbox_probe,
.remove = hi6220_mbox_remove,
}; };
static int __init hi6220_mbox_init(void) static int __init hi6220_mbox_init(void)
......
...@@ -324,14 +324,13 @@ static int imx_mu_probe(struct platform_device *pdev) ...@@ -324,14 +324,13 @@ static int imx_mu_probe(struct platform_device *pdev)
imx_mu_init_generic(priv); 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) static int imx_mu_remove(struct platform_device *pdev)
{ {
struct imx_mu_priv *priv = platform_get_drvdata(pdev); struct imx_mu_priv *priv = platform_get_drvdata(pdev);
mbox_controller_unregister(&priv->mbox);
clk_disable_unprepare(priv->clk); clk_disable_unprepare(priv->clk);
return 0; return 0;
......
...@@ -341,7 +341,7 @@ static int altera_mbox_probe(struct platform_device *pdev) ...@@ -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) { if (ret) {
dev_err(&pdev->dev, "Register mailbox failed\n"); dev_err(&pdev->dev, "Register mailbox failed\n");
goto err; goto err;
...@@ -352,18 +352,6 @@ static int altera_mbox_probe(struct platform_device *pdev) ...@@ -352,18 +352,6 @@ static int altera_mbox_probe(struct platform_device *pdev)
return ret; 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[] = { static const struct of_device_id altera_mbox_match[] = {
{ .compatible = "altr,mailbox-1.0" }, { .compatible = "altr,mailbox-1.0" },
{ /* Sentinel */ } { /* Sentinel */ }
...@@ -373,7 +361,6 @@ MODULE_DEVICE_TABLE(of, altera_mbox_match); ...@@ -373,7 +361,6 @@ MODULE_DEVICE_TABLE(of, altera_mbox_match);
static struct platform_driver altera_mbox_driver = { static struct platform_driver altera_mbox_driver = {
.probe = altera_mbox_probe, .probe = altera_mbox_probe,
.remove = altera_mbox_remove,
.driver = { .driver = {
.name = DRIVER_NAME, .name = DRIVER_NAME,
.of_match_table = altera_mbox_match, .of_match_table = altera_mbox_match,
......
...@@ -462,7 +462,7 @@ static int sti_mbox_probe(struct platform_device *pdev) ...@@ -462,7 +462,7 @@ static int sti_mbox_probe(struct platform_device *pdev)
mbox->chans = chans; mbox->chans = chans;
mbox->num_chans = STI_MBOX_CHAN_MAX; mbox->num_chans = STI_MBOX_CHAN_MAX;
ret = mbox_controller_register(mbox); ret = devm_mbox_controller_register(&pdev->dev, mbox);
if (ret) if (ret)
return ret; return ret;
...@@ -480,7 +480,6 @@ static int sti_mbox_probe(struct platform_device *pdev) ...@@ -480,7 +480,6 @@ static int sti_mbox_probe(struct platform_device *pdev)
IRQF_ONESHOT, mdev->name, mdev); IRQF_ONESHOT, mdev->name, mdev);
if (ret) { if (ret) {
dev_err(&pdev->dev, "Can't claim IRQ %d\n", irq); dev_err(&pdev->dev, "Can't claim IRQ %d\n", irq);
mbox_controller_unregister(mbox);
return -EINVAL; return -EINVAL;
} }
...@@ -489,18 +488,8 @@ static int sti_mbox_probe(struct platform_device *pdev) ...@@ -489,18 +488,8 @@ static int sti_mbox_probe(struct platform_device *pdev)
return 0; 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 = { static struct platform_driver sti_mbox_driver = {
.probe = sti_mbox_probe, .probe = sti_mbox_probe,
.remove = sti_mbox_remove,
.driver = { .driver = {
.name = "sti-mailbox", .name = "sti-mailbox",
.of_match_table = sti_mailbox_match, .of_match_table = sti_mailbox_match,
......
...@@ -224,7 +224,7 @@ static int slimpro_mbox_probe(struct platform_device *pdev) ...@@ -224,7 +224,7 @@ static int slimpro_mbox_probe(struct platform_device *pdev)
ctx->mb_ctrl.ops = &slimpro_mbox_ops; ctx->mb_ctrl.ops = &slimpro_mbox_ops;
ctx->mb_ctrl.num_chans = i; 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) { if (rc) {
dev_err(&pdev->dev, dev_err(&pdev->dev,
"APM X-Gene SLIMpro MailBox register failed:%d\n", rc); "APM X-Gene SLIMpro MailBox register failed:%d\n", rc);
...@@ -235,14 +235,6 @@ static int slimpro_mbox_probe(struct platform_device *pdev) ...@@ -235,14 +235,6 @@ static int slimpro_mbox_probe(struct platform_device *pdev)
return 0; 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[] = { static const struct of_device_id slimpro_of_match[] = {
{.compatible = "apm,xgene-slimpro-mbox" }, {.compatible = "apm,xgene-slimpro-mbox" },
{ }, { },
...@@ -259,7 +251,6 @@ MODULE_DEVICE_TABLE(acpi, slimpro_acpi_ids); ...@@ -259,7 +251,6 @@ MODULE_DEVICE_TABLE(acpi, slimpro_acpi_ids);
static struct platform_driver slimpro_mbox_driver = { static struct platform_driver slimpro_mbox_driver = {
.probe = slimpro_mbox_probe, .probe = slimpro_mbox_probe,
.remove = slimpro_mbox_remove,
.driver = { .driver = {
.name = "xgene-slimpro-mbox", .name = "xgene-slimpro-mbox",
.of_match_table = of_match_ptr(slimpro_of_match), .of_match_table = of_match_ptr(slimpro_of_match),
......
...@@ -283,6 +283,34 @@ int mbox_send_message(struct mbox_chan *chan, void *mssg) ...@@ -283,6 +283,34 @@ int mbox_send_message(struct mbox_chan *chan, void *mssg)
} }
EXPORT_SYMBOL_GPL(mbox_send_message); 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. * mbox_request_channel - Request a mailbox channel.
* @cl: Identity of the client requesting the channel. * @cl: Identity of the client requesting the channel.
...@@ -327,7 +355,8 @@ struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index) ...@@ -327,7 +355,8 @@ struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index)
list_for_each_entry(mbox, &mbox_cons, node) list_for_each_entry(mbox, &mbox_cons, node)
if (mbox->dev->of_node == spec.np) { if (mbox->dev->of_node == spec.np) {
chan = mbox->of_xlate(mbox, &spec); chan = mbox->of_xlate(mbox, &spec);
break; if (!IS_ERR(chan))
break;
} }
of_node_put(spec.np); of_node_put(spec.np);
...@@ -515,3 +544,73 @@ void mbox_controller_unregister(struct mbox_controller *mbox) ...@@ -515,3 +544,73 @@ void mbox_controller_unregister(struct mbox_controller *mbox)
mutex_unlock(&con_mutex); mutex_unlock(&con_mutex);
} }
EXPORT_SYMBOL_GPL(mbox_controller_unregister); 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);
...@@ -337,17 +337,8 @@ static int cmdq_remove(struct platform_device *pdev) ...@@ -337,17 +337,8 @@ static int cmdq_remove(struct platform_device *pdev)
{ {
struct cmdq *cmdq = platform_get_drvdata(pdev); struct cmdq *cmdq = platform_get_drvdata(pdev);
mbox_controller_unregister(&cmdq->mbox);
clk_unprepare(cmdq->clock); 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; return 0;
} }
...@@ -524,7 +515,7 @@ static int cmdq_probe(struct platform_device *pdev) ...@@ -524,7 +515,7 @@ static int cmdq_probe(struct platform_device *pdev)
cmdq->mbox.chans[i].con_priv = (void *)&cmdq->thread[i]; 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) { if (err < 0) {
dev_err(dev, "failed to register mailbox: %d\n", err); dev_err(dev, "failed to register mailbox: %d\n", err);
return err; return err;
......
...@@ -486,7 +486,7 @@ static int omap_mbox_register(struct omap_mbox_device *mdev) ...@@ -486,7 +486,7 @@ static int omap_mbox_register(struct omap_mbox_device *mdev)
list_add(&mdev->elem, &omap_mbox_devices); list_add(&mdev->elem, &omap_mbox_devices);
mutex_unlock(&omap_mbox_devices_lock); mutex_unlock(&omap_mbox_devices_lock);
ret = mbox_controller_register(&mdev->controller); ret = devm_mbox_controller_register(mdev->dev, &mdev->controller);
err_out: err_out:
if (ret) { if (ret) {
...@@ -508,8 +508,6 @@ static int omap_mbox_unregister(struct omap_mbox_device *mdev) ...@@ -508,8 +508,6 @@ static int omap_mbox_unregister(struct omap_mbox_device *mdev)
list_del(&mdev->elem); list_del(&mdev->elem);
mutex_unlock(&omap_mbox_devices_lock); mutex_unlock(&omap_mbox_devices_lock);
mbox_controller_unregister(&mdev->controller);
mboxes = mdev->mboxes; mboxes = mdev->mboxes;
for (i = 0; mboxes[i]; i++) for (i = 0; mboxes[i]; i++)
device_unregister(mboxes[i]->dev); device_unregister(mboxes[i]->dev);
......
...@@ -163,7 +163,7 @@ static int platform_mhu_probe(struct platform_device *pdev) ...@@ -163,7 +163,7 @@ static int platform_mhu_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, mhu); platform_set_drvdata(pdev, mhu);
err = mbox_controller_register(&mhu->mbox); err = devm_mbox_controller_register(dev, &mhu->mbox);
if (err) { if (err) {
dev_err(dev, "Failed to register mailboxes %d\n", err); dev_err(dev, "Failed to register mailboxes %d\n", err);
return err; return err;
...@@ -173,15 +173,6 @@ static int platform_mhu_probe(struct platform_device *pdev) ...@@ -173,15 +173,6 @@ static int platform_mhu_probe(struct platform_device *pdev)
return 0; 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[] = { static const struct of_device_id platform_mhu_dt_ids[] = {
{ .compatible = "amlogic,meson-gxbb-mhu", }, { .compatible = "amlogic,meson-gxbb-mhu", },
{ /* sentinel */ }, { /* sentinel */ },
...@@ -190,7 +181,6 @@ MODULE_DEVICE_TABLE(of, platform_mhu_dt_ids); ...@@ -190,7 +181,6 @@ MODULE_DEVICE_TABLE(of, platform_mhu_dt_ids);
static struct platform_driver platform_mhu_driver = { static struct platform_driver platform_mhu_driver = {
.probe = platform_mhu_probe, .probe = platform_mhu_probe,
.remove = platform_mhu_remove,
.driver = { .driver = {
.name = "platform-mhu", .name = "platform-mhu",
.of_match_table = platform_mhu_dt_ids, .of_match_table = platform_mhu_dt_ids,
......
...@@ -91,7 +91,7 @@ static int qcom_apcs_ipc_probe(struct platform_device *pdev) ...@@ -91,7 +91,7 @@ static int qcom_apcs_ipc_probe(struct platform_device *pdev)
apcs->mbox.chans = apcs->mbox_chans; apcs->mbox.chans = apcs->mbox_chans;
apcs->mbox.num_chans = ARRAY_SIZE(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) { if (ret) {
dev_err(&pdev->dev, "failed to register APCS IPC controller\n"); dev_err(&pdev->dev, "failed to register APCS IPC controller\n");
return ret; return ret;
...@@ -115,7 +115,6 @@ static int qcom_apcs_ipc_remove(struct platform_device *pdev) ...@@ -115,7 +115,6 @@ static int qcom_apcs_ipc_remove(struct platform_device *pdev)
struct qcom_apcs_ipc *apcs = platform_get_drvdata(pdev); struct qcom_apcs_ipc *apcs = platform_get_drvdata(pdev);
struct platform_device *clk = apcs->clk; struct platform_device *clk = apcs->clk;
mbox_controller_unregister(&apcs->mbox);
platform_device_unregister(clk); platform_device_unregister(clk);
return 0; return 0;
......
...@@ -247,28 +247,15 @@ static int rockchip_mbox_probe(struct platform_device *pdev) ...@@ -247,28 +247,15 @@ static int rockchip_mbox_probe(struct platform_device *pdev)
mb->chans[i].msg = NULL; mb->chans[i].msg = NULL;
} }
ret = mbox_controller_register(&mb->mbox); ret = devm_mbox_controller_register(&pdev->dev, &mb->mbox);
if (ret < 0) if (ret < 0)
dev_err(&pdev->dev, "Failed to register mailbox: %d\n", ret); dev_err(&pdev->dev, "Failed to register mailbox: %d\n", ret);
return 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 = { static struct platform_driver rockchip_mbox_driver = {
.probe = rockchip_mbox_probe, .probe = rockchip_mbox_probe,
.remove = rockchip_mbox_remove,
.driver = { .driver = {
.name = "rockchip-mailbox", .name = "rockchip-mailbox",
.of_match_table = of_match_ptr(rockchip_mbox_of_match), .of_match_table = of_match_ptr(rockchip_mbox_of_match),
......
...@@ -299,7 +299,7 @@ static int stm32_ipcc_probe(struct platform_device *pdev) ...@@ -299,7 +299,7 @@ static int stm32_ipcc_probe(struct platform_device *pdev)
for (i = 0; i < ipcc->controller.num_chans; i++) for (i = 0; i < ipcc->controller.num_chans; i++)
ipcc->controller.chans[i].con_priv = (void *)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) if (ret)
goto err_irq_wkp; goto err_irq_wkp;
...@@ -329,8 +329,6 @@ static int stm32_ipcc_remove(struct platform_device *pdev) ...@@ -329,8 +329,6 @@ static int stm32_ipcc_remove(struct platform_device *pdev)
{ {
struct stm32_ipcc *ipcc = platform_get_drvdata(pdev); struct stm32_ipcc *ipcc = platform_get_drvdata(pdev);
mbox_controller_unregister(&ipcc->controller);
if (ipcc->wkp) if (ipcc->wkp)
dev_pm_clear_wake_irq(&pdev->dev); dev_pm_clear_wake_irq(&pdev->dev);
......
This diff is collapsed.
...@@ -547,7 +547,7 @@ static struct mbox_chan *ti_msgmgr_of_xlate(struct mbox_controller *mbox, ...@@ -547,7 +547,7 @@ static struct mbox_chan *ti_msgmgr_of_xlate(struct mbox_controller *mbox,
} }
if (d->is_sproxy) { if (d->is_sproxy) {
if (req_pid > d->num_valid_queues) if (req_pid >= d->num_valid_queues)
goto err; goto err;
qinst = &inst->qinsts[req_pid]; qinst = &inst->qinsts[req_pid];
return qinst->chan; return qinst->chan;
...@@ -817,26 +817,15 @@ static int ti_msgmgr_probe(struct platform_device *pdev) ...@@ -817,26 +817,15 @@ static int ti_msgmgr_probe(struct platform_device *pdev)
mbox->of_xlate = ti_msgmgr_of_xlate; mbox->of_xlate = ti_msgmgr_of_xlate;
platform_set_drvdata(pdev, inst); platform_set_drvdata(pdev, inst);
ret = mbox_controller_register(mbox); ret = devm_mbox_controller_register(dev, mbox);
if (ret) if (ret)
dev_err(dev, "Failed to register mbox_controller(%d)\n", ret); dev_err(dev, "Failed to register mbox_controller(%d)\n", ret);
return ret; return ret;
} }
static int ti_msgmgr_remove(struct platform_device *pdev)
{
struct ti_msgmgr_inst *inst;
inst = platform_get_drvdata(pdev);
mbox_controller_unregister(&inst->mbox);
return 0;
}
static struct platform_driver ti_msgmgr_driver = { static struct platform_driver ti_msgmgr_driver = {
.probe = ti_msgmgr_probe, .probe = ti_msgmgr_probe,
.remove = ti_msgmgr_remove,
.driver = { .driver = {
.name = "ti-msgmgr", .name = "ti-msgmgr",
.of_match_table = of_match_ptr(ti_msgmgr_of_match), .of_match_table = of_match_ptr(ti_msgmgr_of_match),
......
...@@ -22,4 +22,15 @@ ...@@ -22,4 +22,15 @@
#define TEGRA_HSP_DB_MASTER_CCPLEX 17 #define TEGRA_HSP_DB_MASTER_CCPLEX 17
#define TEGRA_HSP_DB_MASTER_BPMP 19 #define TEGRA_HSP_DB_MASTER_BPMP 19
/*
* Shared mailboxes are unidirectional, so the direction needs to be specified
* in the device tree.
*/
#define TEGRA_HSP_SM_MASK 0x00ffffff
#define TEGRA_HSP_SM_FLAG_RX (0 << 31)
#define TEGRA_HSP_SM_FLAG_TX (1 << 31)
#define TEGRA_HSP_SM_RX(x) (TEGRA_HSP_SM_FLAG_RX | ((x) & TEGRA_HSP_SM_MASK))
#define TEGRA_HSP_SM_TX(x) (TEGRA_HSP_SM_FLAG_TX | ((x) & TEGRA_HSP_SM_MASK))
#endif #endif
...@@ -44,6 +44,7 @@ struct mbox_chan *mbox_request_channel_byname(struct mbox_client *cl, ...@@ -44,6 +44,7 @@ struct mbox_chan *mbox_request_channel_byname(struct mbox_client *cl,
const char *name); const char *name);
struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index); struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index);
int mbox_send_message(struct mbox_chan *chan, void *mssg); int mbox_send_message(struct mbox_chan *chan, void *mssg);
int mbox_flush(struct mbox_chan *chan, unsigned long timeout);
void mbox_client_txdone(struct mbox_chan *chan, int r); /* atomic */ void mbox_client_txdone(struct mbox_chan *chan, int r); /* atomic */
bool mbox_client_peek_data(struct mbox_chan *chan); /* atomic */ bool mbox_client_peek_data(struct mbox_chan *chan); /* atomic */
void mbox_free_channel(struct mbox_chan *chan); /* may sleep */ void mbox_free_channel(struct mbox_chan *chan); /* may sleep */
......
...@@ -24,6 +24,9 @@ struct mbox_chan; ...@@ -24,6 +24,9 @@ struct mbox_chan;
* transmission of data is reported by the controller via * transmission of data is reported by the controller via
* mbox_chan_txdone (if it has some TX ACK irq). It must not * mbox_chan_txdone (if it has some TX ACK irq). It must not
* sleep. * sleep.
* @flush: Called when a client requests transmissions to be blocking but
* the context doesn't allow sleeping. Typically the controller
* will implement a busy loop waiting for the data to flush out.
* @startup: Called when a client requests the chan. The controller * @startup: Called when a client requests the chan. The controller
* could ask clients for additional parameters of communication * could ask clients for additional parameters of communication
* to be provided via client's chan_data. This call may * to be provided via client's chan_data. This call may
...@@ -46,6 +49,7 @@ struct mbox_chan; ...@@ -46,6 +49,7 @@ struct mbox_chan;
*/ */
struct mbox_chan_ops { struct mbox_chan_ops {
int (*send_data)(struct mbox_chan *chan, void *data); int (*send_data)(struct mbox_chan *chan, void *data);
int (*flush)(struct mbox_chan *chan, unsigned long timeout);
int (*startup)(struct mbox_chan *chan); int (*startup)(struct mbox_chan *chan);
void (*shutdown)(struct mbox_chan *chan); void (*shutdown)(struct mbox_chan *chan);
bool (*last_tx_done)(struct mbox_chan *chan); bool (*last_tx_done)(struct mbox_chan *chan);
...@@ -131,4 +135,9 @@ void mbox_controller_unregister(struct mbox_controller *mbox); /* can sleep */ ...@@ -131,4 +135,9 @@ void mbox_controller_unregister(struct mbox_controller *mbox); /* can sleep */
void mbox_chan_received_data(struct mbox_chan *chan, void *data); /* atomic */ void mbox_chan_received_data(struct mbox_chan *chan, void *data); /* atomic */
void mbox_chan_txdone(struct mbox_chan *chan, int r); /* atomic */ void mbox_chan_txdone(struct mbox_chan *chan, int r); /* atomic */
int devm_mbox_controller_register(struct device *dev,
struct mbox_controller *mbox);
void devm_mbox_controller_unregister(struct device *dev,
struct mbox_controller *mbox);
#endif /* __MAILBOX_CONTROLLER_H */ #endif /* __MAILBOX_CONTROLLER_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment