Commit 7b2c9e41 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'mailbox-v6.7' of git://git.kernel.org/pub/scm/linux/kernel/git/jassibrar/mailbox

Pull mailbox updates from Jassi Brar:

 - imx: add support for TX Doorbell v2

 - mtk: implement runtime PM

 - zynqmp: add destination mailbox compatible

 - qcom:
    - add another clock provider for IPQ
    - add SM8650 compatible

 - misc: use preferred device_get_match_data()

* tag 'mailbox-v6.7' of git://git.kernel.org/pub/scm/linux/kernel/git/jassibrar/mailbox:
  dt-bindings: mailbox: qcom-ipcc: document the SM8650 Inter-Processor Communication Controller
  mailbox: mtk-cmdq-mailbox: Implement Runtime PM with autosuspend
  mailbox: Use device_get_match_data()
  dt-bindings: zynqmp: add destination mailbox compatible
  dt-bindings: mailbox: qcom: add one more clock provider for IPQ mailbox
  mailbox: imx: support channel type tx doorbell v2
  dt-bindings: mailbox: fsl,mu: add new tx doorbell channel
parents 77fa2fbe 96cb7a4e
......@@ -72,9 +72,9 @@ properties:
type : Channel type
channel : Channel number
This MU support 5 type of unidirectional channels, each type
This MU support 6 type of unidirectional channels, each type
has 4 channels except RST channel which only has 1 channel.
A total of 17 channels. Following types are
A total of 21 channels. Following types are
supported:
0 - TX channel with 32bit transmit register and IRQ transmit
acknowledgment support.
......@@ -82,6 +82,7 @@ properties:
2 - TX doorbell channel. Without own register and no ACK support.
3 - RX doorbell channel.
4 - RST channel
5 - Tx doorbell channel. With S/W ACK from the other side.
const: 2
clocks:
......
......@@ -125,10 +125,12 @@ allOf:
items:
- description: primary pll parent of the clock driver
- description: XO clock
- description: GCC GPLL0 clock source
clock-names:
items:
- const: pll
- const: xo
- const: gpll0
- if:
properties:
......
......@@ -34,6 +34,7 @@ properties:
- qcom,sm8350-ipcc
- qcom,sm8450-ipcc
- qcom,sm8550-ipcc
- qcom,sm8650-ipcc
- const: qcom,ipcc
reg:
......
......@@ -74,6 +74,10 @@ patternProperties:
type: object # DT nodes are json objects
additionalProperties: false
properties:
compatible:
const: xlnx,zynqmp-ipi-dest-mailbox
xlnx,ipi-id:
description:
Remote Xilinx IPI agent ID of which the mailbox is connected to.
......@@ -95,6 +99,7 @@ patternProperties:
- const: remote_response_region
required:
- compatible
- reg
- reg-names
- "#mbox-cells"
......@@ -124,6 +129,7 @@ examples:
ranges;
mailbox: mailbox@ff9905c0 {
compatible = "xlnx,zynqmp-ipi-dest-mailbox";
reg = <0x0 0xff9905c0 0x0 0x20>,
<0x0 0xff9905e0 0x0 0x20>,
<0x0 0xff990e80 0x0 0x20>,
......
......@@ -33,10 +33,9 @@
#include <linux/interrupt.h>
#include <linux/wait.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/mailbox_controller.h>
#include <linux/mailbox/brcm-message.h>
......@@ -1494,7 +1493,6 @@ static int pdc_dt_read(struct platform_device *pdev, struct pdc_state *pdcs)
{
struct device *dev = &pdev->dev;
struct device_node *dn = pdev->dev.of_node;
const struct of_device_id *match;
const int *hw_type;
int err;
......@@ -1509,11 +1507,9 @@ static int pdc_dt_read(struct platform_device *pdev, struct pdc_state *pdcs)
pdcs->hw_type = PDC_HW;
match = of_match_device(of_match_ptr(pdc_mbox_of_match), dev);
if (match != NULL) {
hw_type = match->data;
hw_type = device_get_match_data(dev);
if (hw_type)
pdcs->hw_type = *hw_type;
}
return 0;
}
......
......@@ -20,7 +20,9 @@
#include <linux/suspend.h>
#include <linux/slab.h>
#define IMX_MU_CHANS 17
#include "mailbox.h"
#define IMX_MU_CHANS 24
/* TX0/RX0/RXDB[0-3] */
#define IMX_MU_SCU_CHANS 6
/* TX0/RX0 */
......@@ -39,6 +41,7 @@ enum imx_mu_chan_type {
IMX_MU_TYPE_TXDB = 2, /* Tx doorbell */
IMX_MU_TYPE_RXDB = 3, /* Rx doorbell */
IMX_MU_TYPE_RST = 4, /* Reset */
IMX_MU_TYPE_TXDB_V2 = 5, /* Tx doorbell with S/W ACK */
};
enum imx_mu_xcr {
......@@ -226,6 +229,9 @@ static int imx_mu_generic_tx(struct imx_mu_priv *priv,
imx_mu_xcr_rmw(priv, IMX_MU_GCR, IMX_MU_xCR_GIRn(priv->dcfg->type, cp->idx), 0);
tasklet_schedule(&cp->txdb_tasklet);
break;
case IMX_MU_TYPE_TXDB_V2:
imx_mu_xcr_rmw(priv, IMX_MU_GCR, IMX_MU_xCR_GIRn(priv->dcfg->type, cp->idx), 0);
break;
default:
dev_warn_ratelimited(priv->dev, "Send data on wrong channel type: %d\n", cp->type);
return -EINVAL;
......@@ -554,6 +560,9 @@ static int imx_mu_startup(struct mbox_chan *chan)
int ret;
pm_runtime_get_sync(priv->dev);
if (cp->type == IMX_MU_TYPE_TXDB_V2)
return 0;
if (cp->type == IMX_MU_TYPE_TXDB) {
/* Tx doorbell don't have ACK support */
tasklet_init(&cp->txdb_tasklet, imx_mu_txdb_tasklet,
......@@ -595,6 +604,11 @@ static void imx_mu_shutdown(struct mbox_chan *chan)
int ret;
u32 sr;
if (cp->type == IMX_MU_TYPE_TXDB_V2) {
pm_runtime_put_sync(priv->dev);
return;
}
if (cp->type == IMX_MU_TYPE_TXDB) {
tasklet_kill(&cp->txdb_tasklet);
pm_runtime_put_sync(priv->dev);
......@@ -671,6 +685,7 @@ static struct mbox_chan *imx_mu_specific_xlate(struct mbox_controller *mbox,
static struct mbox_chan * imx_mu_xlate(struct mbox_controller *mbox,
const struct of_phandle_args *sp)
{
struct mbox_chan *p_chan;
u32 type, idx, chan;
if (sp->args_count != 2) {
......@@ -680,14 +695,25 @@ static struct mbox_chan * imx_mu_xlate(struct mbox_controller *mbox,
type = sp->args[0]; /* channel type */
idx = sp->args[1]; /* index */
chan = type * 4 + idx;
/* RST only supports 1 channel */
if ((type == IMX_MU_TYPE_RST) && idx) {
dev_err(mbox->dev, "Invalid RST channel %d\n", idx);
return ERR_PTR(-EINVAL);
}
chan = type * 4 + idx;
if (chan >= mbox->num_chans) {
dev_err(mbox->dev, "Not supported channel number: %d. (type: %d, idx: %d)\n", chan, type, idx);
return ERR_PTR(-EINVAL);
}
return &mbox->chans[chan];
p_chan = &mbox->chans[chan];
if (type == IMX_MU_TYPE_TXDB_V2)
p_chan->txdone_method = TXDONE_BY_ACK;
return p_chan;
}
static struct mbox_chan *imx_mu_seco_xlate(struct mbox_controller *mbox,
......
......@@ -17,8 +17,8 @@
#include <linux/mailbox_controller.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/slab.h>
#include "mailbox.h"
......@@ -403,7 +403,6 @@ MODULE_DEVICE_TABLE(of, sti_mailbox_match);
static int sti_mbox_probe(struct platform_device *pdev)
{
const struct of_device_id *match;
struct mbox_controller *mbox;
struct sti_mbox_device *mdev;
struct device_node *np = pdev->dev.of_node;
......@@ -411,12 +410,11 @@ static int sti_mbox_probe(struct platform_device *pdev)
int irq;
int ret;
match = of_match_device(sti_mailbox_match, &pdev->dev);
if (!match) {
pdev->dev.platform_data = (struct sti_mbox_pdata *)device_get_match_data(&pdev->dev);
if (!pdev->dev.platform_data) {
dev_err(&pdev->dev, "No configuration found\n");
return -ENODEV;
}
pdev->dev.platform_data = (struct sti_mbox_pdata *) match->data;
mdev = devm_kzalloc(&pdev->dev, sizeof(*mdev), GFP_KERNEL);
if (!mdev)
......
......@@ -13,10 +13,13 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/mailbox_controller.h>
#include <linux/mailbox/mtk-cmdq-mailbox.h>
#include <linux/of.h>
#define CMDQ_MBOX_AUTOSUSPEND_DELAY_MS 100
#define CMDQ_OP_CODE_MASK (0xff << CMDQ_OP_CODE_SHIFT)
#define CMDQ_NUM_CMD(t) (t->cmd_buf_size / CMDQ_INST_SIZE)
#define CMDQ_GCE_NUM_MAX (2)
......@@ -283,10 +286,8 @@ static void cmdq_thread_irq_handler(struct cmdq *cmdq,
break;
}
if (list_empty(&thread->task_busy_list)) {
if (list_empty(&thread->task_busy_list))
cmdq_thread_disable(cmdq, thread);
clk_bulk_disable(cmdq->pdata->gce_num, cmdq->clocks);
}
}
static irqreturn_t cmdq_irq_handler(int irq, void *dev)
......@@ -307,9 +308,26 @@ static irqreturn_t cmdq_irq_handler(int irq, void *dev)
spin_unlock_irqrestore(&thread->chan->lock, flags);
}
pm_runtime_mark_last_busy(cmdq->mbox.dev);
return IRQ_HANDLED;
}
static int cmdq_runtime_resume(struct device *dev)
{
struct cmdq *cmdq = dev_get_drvdata(dev);
return clk_bulk_enable(cmdq->pdata->gce_num, cmdq->clocks);
}
static int cmdq_runtime_suspend(struct device *dev)
{
struct cmdq *cmdq = dev_get_drvdata(dev);
clk_bulk_disable(cmdq->pdata->gce_num, cmdq->clocks);
return 0;
}
static int cmdq_suspend(struct device *dev)
{
struct cmdq *cmdq = dev_get_drvdata(dev);
......@@ -333,16 +351,14 @@ static int cmdq_suspend(struct device *dev)
if (cmdq->pdata->sw_ddr_en)
cmdq_sw_ddr_enable(cmdq, false);
clk_bulk_unprepare(cmdq->pdata->gce_num, cmdq->clocks);
return 0;
return pm_runtime_force_suspend(dev);
}
static int cmdq_resume(struct device *dev)
{
struct cmdq *cmdq = dev_get_drvdata(dev);
WARN_ON(clk_bulk_prepare(cmdq->pdata->gce_num, cmdq->clocks));
WARN_ON(pm_runtime_force_resume(dev));
cmdq->suspended = false;
if (cmdq->pdata->sw_ddr_en)
......@@ -358,6 +374,9 @@ static int cmdq_remove(struct platform_device *pdev)
if (cmdq->pdata->sw_ddr_en)
cmdq_sw_ddr_enable(cmdq, false);
if (!IS_ENABLED(CONFIG_PM))
cmdq_runtime_suspend(&pdev->dev);
clk_bulk_unprepare(cmdq->pdata->gce_num, cmdq->clocks);
return 0;
}
......@@ -369,13 +388,20 @@ static int cmdq_mbox_send_data(struct mbox_chan *chan, void *data)
struct cmdq *cmdq = dev_get_drvdata(chan->mbox->dev);
struct cmdq_task *task;
unsigned long curr_pa, end_pa;
int ret;
/* Client should not flush new tasks if suspended. */
WARN_ON(cmdq->suspended);
ret = pm_runtime_get_sync(cmdq->mbox.dev);
if (ret < 0)
return ret;
task = kzalloc(sizeof(*task), GFP_ATOMIC);
if (!task)
if (!task) {
pm_runtime_put_autosuspend(cmdq->mbox.dev);
return -ENOMEM;
}
task->cmdq = cmdq;
INIT_LIST_HEAD(&task->list_entry);
......@@ -384,8 +410,6 @@ static int cmdq_mbox_send_data(struct mbox_chan *chan, void *data)
task->pkt = pkt;
if (list_empty(&thread->task_busy_list)) {
WARN_ON(clk_bulk_enable(cmdq->pdata->gce_num, cmdq->clocks));
/*
* The thread reset will clear thread related register to 0,
* including pc, end, priority, irq, suspend and enable. Thus
......@@ -424,6 +448,9 @@ static int cmdq_mbox_send_data(struct mbox_chan *chan, void *data)
}
list_move_tail(&task->list_entry, &thread->task_busy_list);
pm_runtime_mark_last_busy(cmdq->mbox.dev);
pm_runtime_put_autosuspend(cmdq->mbox.dev);
return 0;
}
......@@ -439,6 +466,8 @@ static void cmdq_mbox_shutdown(struct mbox_chan *chan)
struct cmdq_task *task, *tmp;
unsigned long flags;
WARN_ON(pm_runtime_get_sync(cmdq->mbox.dev));
spin_lock_irqsave(&thread->chan->lock, flags);
if (list_empty(&thread->task_busy_list))
goto done;
......@@ -457,7 +486,6 @@ static void cmdq_mbox_shutdown(struct mbox_chan *chan)
}
cmdq_thread_disable(cmdq, thread);
clk_bulk_disable(cmdq->pdata->gce_num, cmdq->clocks);
done:
/*
......@@ -467,6 +495,9 @@ static void cmdq_mbox_shutdown(struct mbox_chan *chan)
* to do any operation here, only unlock and leave.
*/
spin_unlock_irqrestore(&thread->chan->lock, flags);
pm_runtime_mark_last_busy(cmdq->mbox.dev);
pm_runtime_put_autosuspend(cmdq->mbox.dev);
}
static int cmdq_mbox_flush(struct mbox_chan *chan, unsigned long timeout)
......@@ -477,6 +508,11 @@ static int cmdq_mbox_flush(struct mbox_chan *chan, unsigned long timeout)
struct cmdq_task *task, *tmp;
unsigned long flags;
u32 enable;
int ret;
ret = pm_runtime_get_sync(cmdq->mbox.dev);
if (ret < 0)
return ret;
spin_lock_irqsave(&thread->chan->lock, flags);
if (list_empty(&thread->task_busy_list))
......@@ -497,10 +533,12 @@ static int cmdq_mbox_flush(struct mbox_chan *chan, unsigned long timeout)
cmdq_thread_resume(thread);
cmdq_thread_disable(cmdq, thread);
clk_bulk_disable(cmdq->pdata->gce_num, cmdq->clocks);
out:
spin_unlock_irqrestore(&thread->chan->lock, flags);
pm_runtime_mark_last_busy(cmdq->mbox.dev);
pm_runtime_put_autosuspend(cmdq->mbox.dev);
return 0;
wait:
......@@ -513,6 +551,8 @@ static int cmdq_mbox_flush(struct mbox_chan *chan, unsigned long timeout)
return -EFAULT;
}
pm_runtime_mark_last_busy(cmdq->mbox.dev);
pm_runtime_put_autosuspend(cmdq->mbox.dev);
return 0;
}
......@@ -642,12 +682,28 @@ static int cmdq_probe(struct platform_device *pdev)
return err;
}
/* If Runtime PM is not available enable the clocks now. */
if (!IS_ENABLED(CONFIG_PM)) {
err = cmdq_runtime_resume(dev);
if (err)
return err;
}
err = devm_pm_runtime_enable(dev);
if (err)
return err;
pm_runtime_set_autosuspend_delay(dev, CMDQ_MBOX_AUTOSUSPEND_DELAY_MS);
pm_runtime_use_autosuspend(dev);
return 0;
}
static const struct dev_pm_ops cmdq_pm_ops = {
.suspend = cmdq_suspend,
.resume = cmdq_resume,
SET_RUNTIME_PM_OPS(cmdq_runtime_suspend,
cmdq_runtime_resume, NULL)
};
static const struct gce_plat gce_plat_v2 = {
......
......@@ -15,10 +15,10 @@
#include <linux/kernel.h>
#include <linux/mailbox_controller.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/soc/ti/ti-msgmgr.h>
#define Q_DATA_OFFSET(proxy, queue, reg) \
......@@ -810,7 +810,6 @@ MODULE_DEVICE_TABLE(of, ti_msgmgr_of_match);
static int ti_msgmgr_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
const struct of_device_id *of_id;
struct device_node *np;
const struct ti_msgmgr_desc *desc;
struct ti_msgmgr_inst *inst;
......@@ -828,19 +827,12 @@ static int ti_msgmgr_probe(struct platform_device *pdev)
}
np = dev->of_node;
of_id = of_match_device(ti_msgmgr_of_match, dev);
if (!of_id) {
dev_err(dev, "OF data missing\n");
return -EINVAL;
}
desc = of_id->data;
inst = devm_kzalloc(dev, sizeof(*inst), GFP_KERNEL);
if (!inst)
return -ENOMEM;
inst->dev = dev;
inst->desc = desc;
inst->desc = desc = device_get_match_data(dev);
inst->queue_proxy_region =
devm_platform_ioremap_resource_byname(pdev, desc->data_region_name);
......
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