提交 fde7dc63 编写于 作者: L Linus Torvalds

Merge tag 'mailbox-v5.3' of git://git.linaro.org/landing-teams/working/fujitsu/integration

Pull mailbox updates from Jassi Brar:

 - stm32: race fix by adding a spinlock

 - mhu: trim included headers

 - omap: add support for K3 SoCs

 - imx: Irq disable fix

 - bcm: tidy up extracting driver data

 - tegra: make resume 'noirq'

 - api: fix error handling

* tag 'mailbox-v5.3' of git://git.linaro.org/landing-teams/working/fujitsu/integration:
  mailbox: handle failed named mailbox channel request
  mailbox: tegra: avoid resume NULL mailboxes
  mailbox: tegra: hsp: add noirq resume
  mailbox: bcm-flexrm-mailbox: using dev_get_drvdata directly
  mailbox: imx: Clear GIEn bit at shutdown
  mailbox: omap: Add support for TI K3 SoCs
  dt-bindings: mailbox: omap: Update bindings for TI K3 SoCs
  mailbox: arm_mhu: reorder header inclusion and drop unneeded ones
  mailbox: stm32_ipcc: add spinlock to fix channels concurrent access
OMAP2+ Mailbox Driver
OMAP2+ and K3 Mailbox
=====================
The OMAP mailbox hardware facilitates communication between different processors
......@@ -7,7 +7,7 @@ various processor subsystems and is connected on an interconnect bus. The
communication is achieved through a set of registers for message storage and
interrupt configuration registers.
Each mailbox IP block has a certain number of h/w fifo queues and output
Each mailbox IP block/cluster has a certain number of h/w fifo queues and output
interrupt lines. An output interrupt line is routed to an interrupt controller
within a processor subsystem, and there can be more than one line going to a
specific processor's interrupt controller. The interrupt line connections are
......@@ -23,12 +23,16 @@ All the current OMAP SoCs except for the newest DRA7xx SoC has a single IP
instance. DRA7xx has multiple instances with different number of h/w fifo queues
and interrupt lines between different instances. The interrupt lines can also be
routed to different processor sub-systems on DRA7xx as they are routed through
the Crossbar, a kind of interrupt router/multiplexer.
the Crossbar, a kind of interrupt router/multiplexer. The K3 AM65x and J721E
SoCs has each of these instances form a cluster and combine multiple clusters
into a single IP block present within the Main NavSS. The interrupt lines from
all these clusters are multiplexed and routed to different processor subsystems
over a limited number of common interrupt output lines of an Interrupt Router.
Mailbox Device Node:
====================
A Mailbox device node is used to represent a Mailbox IP instance within a SoC.
The sub-mailboxes are represented as child nodes of this parent node.
A Mailbox device node is used to represent a Mailbox IP instance/cluster within
a SoC. The sub-mailboxes are represented as child nodes of this parent node.
Required properties:
--------------------
......@@ -37,12 +41,12 @@ Required properties:
"ti,omap3-mailbox" for OMAP3430, OMAP3630 SoCs
"ti,omap4-mailbox" for OMAP44xx, OMAP54xx, AM33xx,
AM43xx and DRA7xx SoCs
"ti,am654-mailbox" for K3 AM65x and J721E SoCs
- reg: Contains the mailbox register address range (base
address and length)
- interrupts: Contains the interrupt information for the mailbox
device. The format is dependent on which interrupt
controller the OMAP device uses
- ti,hwmods: Name of the hwmod associated with the mailbox
controller the Mailbox device uses
- #mbox-cells: Common mailbox binding property to identify the number
of cells required for the mailbox specifier. Should be
1
......@@ -50,6 +54,23 @@ Required properties:
device can interrupt
- ti,mbox-num-fifos: Number of h/w fifo queues within the mailbox IP block
SoC-specific Required properties:
---------------------------------
The following are mandatory properties for the OMAP architecture based SoCs
only:
- ti,hwmods: Name of the hwmod associated with the mailbox. This
should be defined in the mailbox node only if the node
is not defined as a child node of a corresponding sysc
interconnect node.
The following are mandatory properties for the K3 AM65x and J721E SoCs only:
- interrupt-parent: Should contain a phandle to the TI-SCI interrupt
controller node that is used to dynamically program
the interrupt routes between the IP and the main GIC
controllers. See the following binding for additional
details,
Documentation/devicetree/bindings/interrupt-controller/ti,sci-intr.txt
Child Nodes:
============
A child node is used for representing the actual sub-mailbox device that is
......@@ -98,7 +119,7 @@ to be used by the client user.
Example:
--------
/* OMAP4 */
1. /* OMAP4 */
mailbox: mailbox@4a0f4000 {
compatible = "ti,omap4-mailbox";
reg = <0x4a0f4000 0x200>;
......@@ -123,7 +144,7 @@ dsp {
...
};
/* AM33xx */
2. /* AM33xx */
mailbox: mailbox@480c8000 {
compatible = "ti,omap4-mailbox";
reg = <0x480C8000 0x200>;
......@@ -137,3 +158,23 @@ mailbox: mailbox@480c8000 {
ti,mbox-rx = <0 0 3>;
};
};
3. /* AM65x */
&cbass_main {
cbass_main_navss: interconnect0 {
mailbox0_cluster0: mailbox@31f80000 {
compatible = "ti,am654-mailbox";
reg = <0x00 0x31f80000 0x00 0x200>;
#mbox-cells = <1>;
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&intr_main_navss>;
interrupts = <164 0>;
mbox_mcu_r5fss0_core0: mbox-mcu-r5fss0-core0 {
ti,mbox-tx = <1 0 0>;
ti,mbox-rx = <0 0 0>;
};
};
};
};
......@@ -54,7 +54,7 @@ config ARMADA_37XX_RWTM_MBOX
config OMAP2PLUS_MBOX
tristate "OMAP2+ Mailbox framework support"
depends on ARCH_OMAP2PLUS
depends on ARCH_OMAP2PLUS || ARCH_K3
help
Mailbox implementation for OMAP family chips with hardware for
interprocessor communication involving DSP, IVA1.0 and IVA2 in
......
......@@ -5,16 +5,13 @@
* Author: Jassi Brar <jaswinder.singh@linaro.org>
*/
#include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/mutex.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/amba/bus.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/amba/bus.h>
#include <linux/mailbox_controller.h>
#include <linux/module.h>
#define INTR_STAT_OFS 0x0
#define INTR_SET_OFS 0x8
......
......@@ -1163,8 +1163,7 @@ static int flexrm_process_completions(struct flexrm_ring *ring)
static int flexrm_debugfs_conf_show(struct seq_file *file, void *offset)
{
struct platform_device *pdev = to_platform_device(file->private);
struct flexrm_mbox *mbox = platform_get_drvdata(pdev);
struct flexrm_mbox *mbox = dev_get_drvdata(file->private);
/* Write config in file */
flexrm_write_config_in_seqfile(mbox, file);
......@@ -1174,8 +1173,7 @@ static int flexrm_debugfs_conf_show(struct seq_file *file, void *offset)
static int flexrm_debugfs_stats_show(struct seq_file *file, void *offset)
{
struct platform_device *pdev = to_platform_device(file->private);
struct flexrm_mbox *mbox = platform_get_drvdata(pdev);
struct flexrm_mbox *mbox = dev_get_drvdata(file->private);
/* Write stats in file */
flexrm_write_stats_in_seqfile(mbox, file);
......
......@@ -217,8 +217,8 @@ static void imx_mu_shutdown(struct mbox_chan *chan)
if (cp->type == IMX_MU_TYPE_TXDB)
tasklet_kill(&cp->txdb_tasklet);
imx_mu_xcr_rmw(priv, 0,
IMX_MU_xCR_TIEn(cp->idx) | IMX_MU_xCR_RIEn(cp->idx));
imx_mu_xcr_rmw(priv, 0, IMX_MU_xCR_TIEn(cp->idx) |
IMX_MU_xCR_RIEn(cp->idx) | IMX_MU_xCR_GIEn(cp->idx));
free_irq(priv->irq, chan);
}
......
......@@ -418,11 +418,13 @@ struct mbox_chan *mbox_request_channel_byname(struct mbox_client *cl,
of_property_for_each_string(np, "mbox-names", prop, mbox_name) {
if (!strncmp(name, mbox_name, strlen(name)))
break;
return mbox_request_channel(cl, index);
index++;
}
return mbox_request_channel(cl, index);
dev_err(cl->dev, "%s() could not locate channel named \"%s\"\n",
__func__, name);
return ERR_PTR(-EINVAL);
}
EXPORT_SYMBOL_GPL(mbox_request_channel_byname);
......
......@@ -3,7 +3,7 @@
* OMAP mailbox driver
*
* Copyright (C) 2006-2009 Nokia Corporation. All rights reserved.
* Copyright (C) 2013-2016 Texas Instruments Incorporated - http://www.ti.com
* Copyright (C) 2013-2019 Texas Instruments Incorporated - http://www.ti.com
*
* Contact: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
* Suman Anna <s-anna@ti.com>
......@@ -141,14 +141,14 @@ void mbox_write_reg(struct omap_mbox_device *mdev, u32 val, size_t ofs)
}
/* Mailbox FIFO handle functions */
static mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox)
static u32 mbox_fifo_read(struct omap_mbox *mbox)
{
struct omap_mbox_fifo *fifo = &mbox->rx_fifo;
return (mbox_msg_t)mbox_read_reg(mbox->parent, fifo->msg);
return mbox_read_reg(mbox->parent, fifo->msg);
}
static void mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg)
static void mbox_fifo_write(struct omap_mbox *mbox, u32 msg)
{
struct omap_mbox_fifo *fifo = &mbox->tx_fifo;
......@@ -256,14 +256,16 @@ static void mbox_rx_work(struct work_struct *work)
{
struct omap_mbox_queue *mq =
container_of(work, struct omap_mbox_queue, work);
mbox_msg_t msg;
mbox_msg_t data;
u32 msg;
int len;
while (kfifo_len(&mq->fifo) >= sizeof(msg)) {
len = kfifo_out(&mq->fifo, (unsigned char *)&msg, sizeof(msg));
WARN_ON(len != sizeof(msg));
data = msg;
mbox_chan_received_data(mq->mbox->chan, (void *)msg);
mbox_chan_received_data(mq->mbox->chan, (void *)data);
spin_lock_irq(&mq->lock);
if (mq->full) {
mq->full = false;
......@@ -286,7 +288,7 @@ static void __mbox_tx_interrupt(struct omap_mbox *mbox)
static void __mbox_rx_interrupt(struct omap_mbox *mbox)
{
struct omap_mbox_queue *mq = mbox->rxq;
mbox_msg_t msg;
u32 msg;
int len;
while (!mbox_fifo_empty(mbox)) {
......@@ -540,13 +542,13 @@ static void omap_mbox_chan_shutdown(struct mbox_chan *chan)
mutex_unlock(&mdev->cfg_lock);
}
static int omap_mbox_chan_send_noirq(struct omap_mbox *mbox, void *data)
static int omap_mbox_chan_send_noirq(struct omap_mbox *mbox, u32 msg)
{
int ret = -EBUSY;
if (!mbox_fifo_full(mbox)) {
_omap_mbox_enable_irq(mbox, IRQ_RX);
mbox_fifo_write(mbox, (mbox_msg_t)data);
mbox_fifo_write(mbox, msg);
ret = 0;
_omap_mbox_disable_irq(mbox, IRQ_RX);
......@@ -558,12 +560,12 @@ static int omap_mbox_chan_send_noirq(struct omap_mbox *mbox, void *data)
return ret;
}
static int omap_mbox_chan_send(struct omap_mbox *mbox, void *data)
static int omap_mbox_chan_send(struct omap_mbox *mbox, u32 msg)
{
int ret = -EBUSY;
if (!mbox_fifo_full(mbox)) {
mbox_fifo_write(mbox, (mbox_msg_t)data);
mbox_fifo_write(mbox, msg);
ret = 0;
}
......@@ -576,14 +578,15 @@ static int omap_mbox_chan_send_data(struct mbox_chan *chan, void *data)
{
struct omap_mbox *mbox = mbox_chan_to_omap_mbox(chan);
int ret;
u32 msg = omap_mbox_message(data);
if (!mbox)
return -EINVAL;
if (mbox->send_no_irq)
ret = omap_mbox_chan_send_noirq(mbox, data);
ret = omap_mbox_chan_send_noirq(mbox, msg);
else
ret = omap_mbox_chan_send(mbox, data);
ret = omap_mbox_chan_send(mbox, msg);
return ret;
}
......@@ -656,6 +659,10 @@ static const struct of_device_id omap_mailbox_of_match[] = {
.compatible = "ti,omap4-mailbox",
.data = &omap4_data,
},
{
.compatible = "ti,am654-mailbox",
.data = &omap4_data,
},
{
/* end */
},
......@@ -830,7 +837,10 @@ static int omap_mbox_probe(struct platform_device *pdev)
mdev->intr_type = intr_type;
mdev->mboxes = list;
/* OMAP does not have a Tx-Done IRQ, but rather a Tx-Ready IRQ */
/*
* OMAP/K3 Mailbox IP does not have a Tx-Done IRQ, but rather a Tx-Ready
* IRQ and is needed to run the Tx state machine
*/
mdev->controller.txdone_irq = true;
mdev->controller.dev = mdev->dev;
mdev->controller.ops = &omap_mbox_chan_ops;
......@@ -899,9 +909,8 @@ static int __init omap_mbox_init(void)
return err;
/* kfifo size sanity check: alignment and minimal size */
mbox_kfifo_size = ALIGN(mbox_kfifo_size, sizeof(mbox_msg_t));
mbox_kfifo_size = max_t(unsigned int, mbox_kfifo_size,
sizeof(mbox_msg_t));
mbox_kfifo_size = ALIGN(mbox_kfifo_size, sizeof(u32));
mbox_kfifo_size = max_t(unsigned int, mbox_kfifo_size, sizeof(u32));
err = platform_driver_register(&omap_mbox_driver);
if (err)
......
......@@ -50,6 +50,7 @@ struct stm32_ipcc {
void __iomem *reg_base;
void __iomem *reg_proc;
struct clk *clk;
spinlock_t lock; /* protect access to IPCC registers */
int irqs[IPCC_IRQ_NUM];
int wkp;
u32 proc_id;
......@@ -58,14 +59,24 @@ struct stm32_ipcc {
u32 xmr;
};
static inline void stm32_ipcc_set_bits(void __iomem *reg, u32 mask)
static inline void stm32_ipcc_set_bits(spinlock_t *lock, void __iomem *reg,
u32 mask)
{
unsigned long flags;
spin_lock_irqsave(lock, flags);
writel_relaxed(readl_relaxed(reg) | mask, reg);
spin_unlock_irqrestore(lock, flags);
}
static inline void stm32_ipcc_clr_bits(void __iomem *reg, u32 mask)
static inline void stm32_ipcc_clr_bits(spinlock_t *lock, void __iomem *reg,
u32 mask)
{
unsigned long flags;
spin_lock_irqsave(lock, flags);
writel_relaxed(readl_relaxed(reg) & ~mask, reg);
spin_unlock_irqrestore(lock, flags);
}
static irqreturn_t stm32_ipcc_rx_irq(int irq, void *data)
......@@ -92,7 +103,7 @@ static irqreturn_t stm32_ipcc_rx_irq(int irq, void *data)
mbox_chan_received_data(&ipcc->controller.chans[chan], NULL);
stm32_ipcc_set_bits(ipcc->reg_proc + IPCC_XSCR,
stm32_ipcc_set_bits(&ipcc->lock, ipcc->reg_proc + IPCC_XSCR,
RX_BIT_CHAN(chan));
ret = IRQ_HANDLED;
......@@ -121,7 +132,7 @@ static irqreturn_t stm32_ipcc_tx_irq(int irq, void *data)
dev_dbg(dev, "%s: chan:%d tx\n", __func__, chan);
/* mask 'tx channel free' interrupt */
stm32_ipcc_set_bits(ipcc->reg_proc + IPCC_XMR,
stm32_ipcc_set_bits(&ipcc->lock, ipcc->reg_proc + IPCC_XMR,
TX_BIT_CHAN(chan));
mbox_chan_txdone(&ipcc->controller.chans[chan], 0);
......@@ -141,10 +152,12 @@ static int stm32_ipcc_send_data(struct mbox_chan *link, void *data)
dev_dbg(ipcc->controller.dev, "%s: chan:%d\n", __func__, chan);
/* set channel n occupied */
stm32_ipcc_set_bits(ipcc->reg_proc + IPCC_XSCR, TX_BIT_CHAN(chan));
stm32_ipcc_set_bits(&ipcc->lock, ipcc->reg_proc + IPCC_XSCR,
TX_BIT_CHAN(chan));
/* unmask 'tx channel free' interrupt */
stm32_ipcc_clr_bits(ipcc->reg_proc + IPCC_XMR, TX_BIT_CHAN(chan));
stm32_ipcc_clr_bits(&ipcc->lock, ipcc->reg_proc + IPCC_XMR,
TX_BIT_CHAN(chan));
return 0;
}
......@@ -163,7 +176,8 @@ static int stm32_ipcc_startup(struct mbox_chan *link)
}
/* unmask 'rx channel occupied' interrupt */
stm32_ipcc_clr_bits(ipcc->reg_proc + IPCC_XMR, RX_BIT_CHAN(chan));
stm32_ipcc_clr_bits(&ipcc->lock, ipcc->reg_proc + IPCC_XMR,
RX_BIT_CHAN(chan));
return 0;
}
......@@ -175,7 +189,7 @@ static void stm32_ipcc_shutdown(struct mbox_chan *link)
controller);
/* mask rx/tx interrupt */
stm32_ipcc_set_bits(ipcc->reg_proc + IPCC_XMR,
stm32_ipcc_set_bits(&ipcc->lock, ipcc->reg_proc + IPCC_XMR,
RX_BIT_CHAN(chan) | TX_BIT_CHAN(chan));
clk_disable_unprepare(ipcc->clk);
......@@ -208,6 +222,8 @@ static int stm32_ipcc_probe(struct platform_device *pdev)
if (!ipcc)
return -ENOMEM;
spin_lock_init(&ipcc->lock);
/* proc_id */
if (of_property_read_u32(np, "st,proc-id", &ipcc->proc_id)) {
dev_err(dev, "Missing st,proc-id\n");
......@@ -259,9 +275,10 @@ static int stm32_ipcc_probe(struct platform_device *pdev)
}
/* mask and enable rx/tx irq */
stm32_ipcc_set_bits(ipcc->reg_proc + IPCC_XMR,
stm32_ipcc_set_bits(&ipcc->lock, ipcc->reg_proc + IPCC_XMR,
RX_BIT_MASK | TX_BIT_MASK);
stm32_ipcc_set_bits(ipcc->reg_proc + IPCC_XCR, XCR_RXOIE | XCR_TXOIE);
stm32_ipcc_set_bits(&ipcc->lock, ipcc->reg_proc + IPCC_XCR,
XCR_RXOIE | XCR_TXOIE);
/* wakeup */
if (of_property_read_bool(np, "wakeup-source")) {
......
......@@ -775,18 +775,28 @@ static int __maybe_unused tegra_hsp_resume(struct device *dev)
{
struct tegra_hsp *hsp = dev_get_drvdata(dev);
unsigned int i;
struct tegra_hsp_doorbell *db;
for (i = 0; i < hsp->num_sm; i++) {
struct tegra_hsp_mailbox *mb = &hsp->mailboxes[i];
list_for_each_entry(db, &hsp->doorbells, list) {
if (db && db->channel.chan)
tegra_hsp_doorbell_startup(db->channel.chan);
}
if (hsp->mailboxes) {
for (i = 0; i < hsp->num_sm; i++) {
struct tegra_hsp_mailbox *mb = &hsp->mailboxes[i];
if (mb->channel.chan->cl)
tegra_hsp_mailbox_startup(mb->channel.chan);
if (mb->channel.chan->cl)
tegra_hsp_mailbox_startup(mb->channel.chan);
}
}
return 0;
}
static SIMPLE_DEV_PM_OPS(tegra_hsp_pm_ops, NULL, tegra_hsp_resume);
static const struct dev_pm_ops tegra_hsp_pm_ops = {
.resume_noirq = tegra_hsp_resume,
};
static const struct tegra_hsp_db_map tegra186_hsp_db_map[] = {
{ "ccplex", TEGRA_HSP_DB_MASTER_CCPLEX, HSP_DB_CCPLEX, },
......
......@@ -6,7 +6,9 @@
#ifndef OMAP_MAILBOX_H
#define OMAP_MAILBOX_H
typedef u32 mbox_msg_t;
typedef uintptr_t mbox_msg_t;
#define omap_mbox_message(data) (u32)(mbox_msg_t)(data)
typedef int __bitwise omap_mbox_irq_t;
#define IRQ_TX ((__force omap_mbox_irq_t) 1)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册