Commit d8201efe authored by Linus Torvalds's avatar Linus Torvalds

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

Pull mailbox updates from Jassi Brar:
 "qcom:
   - enable support for SM8350 and SC7280

  sprd:
   - refcount channel usage
   - specify interrupt names in dt
   - support sc9863a

  arm:
   - drop redundant print

  ti:
   - convert dt-bindings to json schema

  and misc spelling fixes"

* tag 'mailbox-v5.13' of git://git.linaro.org/landing-teams/working/fujitsu/integration:
  dt-bindings: mailbox: qcom-ipcc: Add compatible for SC7280
  dt-bindings: mailbox: ti,secure-proxy: Convert to json schema
  mailbox: arm_mhu_db: Remove redundant dev_err call in mhu_db_probe()
  mailbox: sprd: Add supplementary inbox support
  dt-bindings: mailbox: Add interrupt-names to SPRD mailbox
  mailbox: sprd: Introduce refcnt when clients requests/free channels
  MAINTAINERS: Add DT bindings directory to mailbox
  mailbox: fix various typos in comments
  mailbox: pcc: fix platform_no_drv_owner.cocci warnings
  dt-bindings: mailbox: Add compatible for SM8350 IPCC
parents c969f245 2335f556
...@@ -25,6 +25,8 @@ properties: ...@@ -25,6 +25,8 @@ properties:
items: items:
- enum: - enum:
- qcom,sm8250-ipcc - qcom,sm8250-ipcc
- qcom,sm8350-ipcc
- qcom,sc7280-ipcc
- const: qcom,ipcc - const: qcom,ipcc
reg: reg:
......
...@@ -15,6 +15,7 @@ properties: ...@@ -15,6 +15,7 @@ properties:
compatible: compatible:
enum: enum:
- sprd,sc9860-mailbox - sprd,sc9860-mailbox
- sprd,sc9863a-mailbox
reg: reg:
items: items:
...@@ -22,9 +23,15 @@ properties: ...@@ -22,9 +23,15 @@ properties:
- description: outbox registers' base address - description: outbox registers' base address
interrupts: interrupts:
minItems: 2
maxItems: 3
interrupt-names:
minItems: 2
items: items:
- description: inbox interrupt - const: inbox
- description: outbox interrupt - const: outbox
- const: supp-outbox
clocks: clocks:
maxItems: 1 maxItems: 1
...@@ -40,6 +47,7 @@ required: ...@@ -40,6 +47,7 @@ required:
- compatible - compatible
- reg - reg
- interrupts - interrupts
- interrupt-names
- "#mbox-cells" - "#mbox-cells"
- clocks - clocks
- clock-names - clock-names
...@@ -56,5 +64,6 @@ examples: ...@@ -56,5 +64,6 @@ examples:
clock-names = "enable"; clock-names = "enable";
clocks = <&aon_gate 53>; clocks = <&aon_gate 53>;
interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>; interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "inbox", "outbox";
}; };
... ...
Texas Instruments' Secure Proxy
========================================
The Texas Instruments' secure proxy is a mailbox controller that has
configurable queues selectable at SoC(System on Chip) integration. The
Message manager is broken up into different address regions that are
called "threads" or "proxies" - each instance is unidirectional and is
instantiated at SoC integration level by system controller to indicate
receive or transmit path.
Message Manager Device Node:
===========================
Required properties:
--------------------
- compatible: Shall be "ti,am654-secure-proxy"
- reg-names target_data - Map the proxy data region
rt - Map the realtime status region
scfg - Map the configuration region
- reg: Contains the register map per reg-names.
- #mbox-cells Shall be 1 and shall refer to the transfer path
called thread.
- interrupt-names: Contains interrupt names matching the rx transfer path
for a given SoC. Receive interrupts shall be of the
format: "rx_<PID>".
- interrupts: Contains the interrupt information corresponding to
interrupt-names property.
Example(AM654):
------------
secure_proxy: mailbox@32c00000 {
compatible = "ti,am654-secure-proxy";
#mbox-cells = <1>;
reg-names = "target_data", "rt", "scfg";
reg = <0x0 0x32c00000 0x0 0x100000>,
<0x0 0x32400000 0x0 0x100000>,
<0x0 0x32800000 0x0 0x100000>;
interrupt-names = "rx_011";
interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
};
dmsc: dmsc {
[...]
mbox-names = "rx", "tx";
# RX Thread ID is 11
# TX Thread ID is 13
mboxes= <&secure_proxy 11>,
<&secure_proxy 13>;
[...]
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/mailbox/ti,secure-proxy.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Texas Instruments' Secure Proxy
maintainers:
- Nishanth Menon <nm@ti.com>
description: |
The Texas Instruments' secure proxy is a mailbox controller that has
configurable queues selectable at SoC(System on Chip) integration. The
Message manager is broken up into different address regions that are
called "threads" or "proxies" - each instance is unidirectional and is
instantiated at SoC integration level by system controller to indicate
receive or transmit path.
properties:
$nodename:
pattern: "^mailbox@[0-9a-f]+$"
compatible:
const: ti,am654-secure-proxy
"#mbox-cells":
const: 1
description:
Contains the secure proxy thread ID used for the specific transfer path.
reg-names:
items:
- const: target_data
- const: rt
- const: scfg
reg:
minItems: 3
interrupt-names:
minItems: 1
maxItems: 100
items:
pattern: "^rx_[0-9]{3}$"
description:
Contains the interrupt name information for the Rx interrupt path for
secure proxy thread in the form 'rx_<PID>'.
interrupts:
minItems: 1
maxItems: 100
description:
Contains the interrupt information for the Rx interrupt path for secure
proxy.
required:
- compatible
- reg-names
- reg
- interrupt-names
- interrupts
- "#mbox-cells"
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
secure_proxy: mailbox@32c00000 {
compatible = "ti,am654-secure-proxy";
#mbox-cells = <1>;
reg-names = "target_data", "rt", "scfg";
reg = <0x32c00000 0x100000>,
<0x32400000 0x100000>,
<0x32800000 0x100000>;
interrupt-names = "rx_011";
interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
};
...@@ -10772,6 +10772,7 @@ S: Maintained ...@@ -10772,6 +10772,7 @@ S: Maintained
F: drivers/mailbox/ F: drivers/mailbox/
F: include/linux/mailbox_client.h F: include/linux/mailbox_client.h
F: include/linux/mailbox_controller.h F: include/linux/mailbox_controller.h
F: Documentation/devicetree/bindings/mailbox/
MAILBOX ARM MHUv2 MAILBOX ARM MHUv2
M: Viresh Kumar <viresh.kumar@linaro.org> M: Viresh Kumar <viresh.kumar@linaro.org>
......
...@@ -78,7 +78,7 @@ config OMAP_MBOX_KFIFO_SIZE ...@@ -78,7 +78,7 @@ config OMAP_MBOX_KFIFO_SIZE
module parameter). module parameter).
config ROCKCHIP_MBOX config ROCKCHIP_MBOX
bool "Rockchip Soc Intergrated Mailbox Support" bool "Rockchip Soc Integrated Mailbox Support"
depends on ARCH_ROCKCHIP || COMPILE_TEST depends on ARCH_ROCKCHIP || COMPILE_TEST
help help
This driver provides support for inter-processor communication This driver provides support for inter-processor communication
......
...@@ -278,10 +278,8 @@ static int mhu_db_probe(struct amba_device *adev, const struct amba_id *id) ...@@ -278,10 +278,8 @@ static int mhu_db_probe(struct amba_device *adev, const struct amba_id *id)
return -ENOMEM; return -ENOMEM;
mhu->base = devm_ioremap_resource(dev, &adev->res); mhu->base = devm_ioremap_resource(dev, &adev->res);
if (IS_ERR(mhu->base)) { if (IS_ERR(mhu->base))
dev_err(dev, "ioremap failed\n");
return PTR_ERR(mhu->base); return PTR_ERR(mhu->base);
}
chans = devm_kcalloc(dev, max_chans, sizeof(*chans), GFP_KERNEL); chans = devm_kcalloc(dev, max_chans, sizeof(*chans), GFP_KERNEL);
if (!chans) if (!chans)
......
...@@ -423,7 +423,7 @@ static void flexrm_enqueue_desc(u32 nhpos, u32 nhcnt, u32 reqid, ...@@ -423,7 +423,7 @@ static void flexrm_enqueue_desc(u32 nhpos, u32 nhcnt, u32 reqid,
* *
* In general use, number of non-HEADER descriptors can easily go * In general use, number of non-HEADER descriptors can easily go
* beyond 31. To tackle this situation, we have packet (or request) * beyond 31. To tackle this situation, we have packet (or request)
* extenstion bits (STARTPKT and ENDPKT) in the HEADER descriptor. * extension bits (STARTPKT and ENDPKT) in the HEADER descriptor.
* *
* To use packet extension, the first HEADER descriptor of request * To use packet extension, the first HEADER descriptor of request
* (or packet) will have STARTPKT=1 and ENDPKT=0. The intermediate * (or packet) will have STARTPKT=1 and ENDPKT=0. The intermediate
...@@ -1095,7 +1095,7 @@ static int flexrm_process_completions(struct flexrm_ring *ring) ...@@ -1095,7 +1095,7 @@ static int flexrm_process_completions(struct flexrm_ring *ring)
/* /*
* Get current completion read and write offset * Get current completion read and write offset
* *
* Note: We should read completion write pointer atleast once * Note: We should read completion write pointer at least once
* after we get a MSI interrupt because HW maintains internal * after we get a MSI interrupt because HW maintains internal
* MSI status which will allow next MSI interrupt only after * MSI status which will allow next MSI interrupt only after
* completion write pointer is read. * completion write pointer is read.
......
...@@ -51,10 +51,10 @@ struct slimpro_mbox_chan { ...@@ -51,10 +51,10 @@ struct slimpro_mbox_chan {
/** /**
* X-Gene SlimPRO Mailbox controller data * X-Gene SlimPRO Mailbox controller data
* *
* X-Gene SlimPRO Mailbox controller has 8 commnunication channels. * X-Gene SlimPRO Mailbox controller has 8 communication channels.
* Each channel has a separate IRQ number assgined to it. * Each channel has a separate IRQ number assigned to it.
* *
* @mb_ctrl: Representation of the commnunication channel controller * @mb_ctrl: Representation of the communication channel controller
* @mc: Array of SlimPRO mailbox channels of the controller * @mc: Array of SlimPRO mailbox channels of the controller
* @chans: Array of mailbox communication channels * @chans: Array of mailbox communication channels
* *
......
...@@ -5,6 +5,6 @@ ...@@ -5,6 +5,6 @@
#define TXDONE_BY_IRQ BIT(0) /* controller has remote RTR irq */ #define TXDONE_BY_IRQ BIT(0) /* controller has remote RTR irq */
#define TXDONE_BY_POLL BIT(1) /* controller can read status of last TX */ #define TXDONE_BY_POLL BIT(1) /* controller can read status of last TX */
#define TXDONE_BY_ACK BIT(2) /* S/W ACK recevied by Client ticks the TX */ #define TXDONE_BY_ACK BIT(2) /* S/W ACK received by Client ticks the TX */
#endif /* __MAILBOX_H */ #endif /* __MAILBOX_H */
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
* * Client writes WRITE cmd in communication region cmd address. * * Client writes WRITE cmd in communication region cmd address.
* * Client issues mbox_send_message() which rings the PCC doorbell * * Client issues mbox_send_message() which rings the PCC doorbell
* for its PCC channel. * for its PCC channel.
* * If command completes, then writes have succeded and it can release * * If command completes, then writes have succeeded and it can release
* the channel lock. * the channel lock.
* *
* There is a Nominal latency defined for each channel which indicates * There is a Nominal latency defined for each channel which indicates
...@@ -577,7 +577,6 @@ static struct platform_driver pcc_mbox_driver = { ...@@ -577,7 +577,6 @@ static struct platform_driver pcc_mbox_driver = {
.probe = pcc_mbox_probe, .probe = pcc_mbox_probe,
.driver = { .driver = {
.name = "PCCT", .name = "PCCT",
.owner = THIS_MODULE,
}, },
}; };
......
...@@ -73,7 +73,7 @@ static u32 __ipc_rcv(int mbox, u32 *data) ...@@ -73,7 +73,7 @@ static u32 __ipc_rcv(int mbox, u32 *data)
return data[1]; return data[1];
} }
/* blocking implmentation from the A9 side, not usuable in interrupts! */ /* blocking implementation from the A9 side, not usable in interrupts! */
int pl320_ipc_transmit(u32 *data) int pl320_ipc_transmit(u32 *data)
{ {
int ret; int ret;
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/mailbox_controller.h> #include <linux/mailbox_controller.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/clk.h> #include <linux/clk.h>
...@@ -25,41 +26,47 @@ ...@@ -25,41 +26,47 @@
#define SPRD_MBOX_LOCK 0x20 #define SPRD_MBOX_LOCK 0x20
#define SPRD_MBOX_FIFO_DEPTH 0x24 #define SPRD_MBOX_FIFO_DEPTH 0x24
/* Bit and mask definiation for inbox's SPRD_MBOX_FIFO_STS register */ /* Bit and mask definition for inbox's SPRD_MBOX_FIFO_STS register */
#define SPRD_INBOX_FIFO_DELIVER_MASK GENMASK(23, 16) #define SPRD_INBOX_FIFO_DELIVER_MASK GENMASK(23, 16)
#define SPRD_INBOX_FIFO_OVERLOW_MASK GENMASK(15, 8) #define SPRD_INBOX_FIFO_OVERLOW_MASK GENMASK(15, 8)
#define SPRD_INBOX_FIFO_DELIVER_SHIFT 16 #define SPRD_INBOX_FIFO_DELIVER_SHIFT 16
#define SPRD_INBOX_FIFO_BUSY_MASK GENMASK(7, 0) #define SPRD_INBOX_FIFO_BUSY_MASK GENMASK(7, 0)
/* Bit and mask definiation for SPRD_MBOX_IRQ_STS register */ /* Bit and mask definition for SPRD_MBOX_IRQ_STS register */
#define SPRD_MBOX_IRQ_CLR BIT(0) #define SPRD_MBOX_IRQ_CLR BIT(0)
/* Bit and mask definiation for outbox's SPRD_MBOX_FIFO_STS register */ /* Bit and mask definition for outbox's SPRD_MBOX_FIFO_STS register */
#define SPRD_OUTBOX_FIFO_FULL BIT(2) #define SPRD_OUTBOX_FIFO_FULL BIT(2)
#define SPRD_OUTBOX_FIFO_WR_SHIFT 16 #define SPRD_OUTBOX_FIFO_WR_SHIFT 16
#define SPRD_OUTBOX_FIFO_RD_SHIFT 24 #define SPRD_OUTBOX_FIFO_RD_SHIFT 24
#define SPRD_OUTBOX_FIFO_POS_MASK GENMASK(7, 0) #define SPRD_OUTBOX_FIFO_POS_MASK GENMASK(7, 0)
/* Bit and mask definiation for inbox's SPRD_MBOX_IRQ_MSK register */ /* Bit and mask definition for inbox's SPRD_MBOX_IRQ_MSK register */
#define SPRD_INBOX_FIFO_BLOCK_IRQ BIT(0) #define SPRD_INBOX_FIFO_BLOCK_IRQ BIT(0)
#define SPRD_INBOX_FIFO_OVERFLOW_IRQ BIT(1) #define SPRD_INBOX_FIFO_OVERFLOW_IRQ BIT(1)
#define SPRD_INBOX_FIFO_DELIVER_IRQ BIT(2) #define SPRD_INBOX_FIFO_DELIVER_IRQ BIT(2)
#define SPRD_INBOX_FIFO_IRQ_MASK GENMASK(2, 0) #define SPRD_INBOX_FIFO_IRQ_MASK GENMASK(2, 0)
/* Bit and mask definiation for outbox's SPRD_MBOX_IRQ_MSK register */ /* Bit and mask definition for outbox's SPRD_MBOX_IRQ_MSK register */
#define SPRD_OUTBOX_FIFO_NOT_EMPTY_IRQ BIT(0) #define SPRD_OUTBOX_FIFO_NOT_EMPTY_IRQ BIT(0)
#define SPRD_OUTBOX_FIFO_IRQ_MASK GENMASK(4, 0) #define SPRD_OUTBOX_FIFO_IRQ_MASK GENMASK(4, 0)
#define SPRD_OUTBOX_BASE_SPAN 0x1000
#define SPRD_MBOX_CHAN_MAX 8 #define SPRD_MBOX_CHAN_MAX 8
#define SPRD_SUPP_INBOX_ID_SC9863A 7
struct sprd_mbox_priv { struct sprd_mbox_priv {
struct mbox_controller mbox; struct mbox_controller mbox;
struct device *dev; struct device *dev;
void __iomem *inbox_base; void __iomem *inbox_base;
void __iomem *outbox_base; void __iomem *outbox_base;
/* Base register address for supplementary outbox */
void __iomem *supp_base;
struct clk *clk; struct clk *clk;
u32 outbox_fifo_depth; u32 outbox_fifo_depth;
struct mutex lock;
u32 refcnt;
struct mbox_chan chan[SPRD_MBOX_CHAN_MAX]; struct mbox_chan chan[SPRD_MBOX_CHAN_MAX];
}; };
...@@ -94,14 +101,13 @@ static u32 sprd_mbox_get_fifo_len(struct sprd_mbox_priv *priv, u32 fifo_sts) ...@@ -94,14 +101,13 @@ static u32 sprd_mbox_get_fifo_len(struct sprd_mbox_priv *priv, u32 fifo_sts)
return fifo_len; return fifo_len;
} }
static irqreturn_t sprd_mbox_outbox_isr(int irq, void *data) static irqreturn_t do_outbox_isr(void __iomem *base, struct sprd_mbox_priv *priv)
{ {
struct sprd_mbox_priv *priv = data;
struct mbox_chan *chan; struct mbox_chan *chan;
u32 fifo_sts, fifo_len, msg[2]; u32 fifo_sts, fifo_len, msg[2];
int i, id; int i, id;
fifo_sts = readl(priv->outbox_base + SPRD_MBOX_FIFO_STS); fifo_sts = readl(base + SPRD_MBOX_FIFO_STS);
fifo_len = sprd_mbox_get_fifo_len(priv, fifo_sts); fifo_len = sprd_mbox_get_fifo_len(priv, fifo_sts);
if (!fifo_len) { if (!fifo_len) {
...@@ -110,23 +116,41 @@ static irqreturn_t sprd_mbox_outbox_isr(int irq, void *data) ...@@ -110,23 +116,41 @@ static irqreturn_t sprd_mbox_outbox_isr(int irq, void *data)
} }
for (i = 0; i < fifo_len; i++) { for (i = 0; i < fifo_len; i++) {
msg[0] = readl(priv->outbox_base + SPRD_MBOX_MSG_LOW); msg[0] = readl(base + SPRD_MBOX_MSG_LOW);
msg[1] = readl(priv->outbox_base + SPRD_MBOX_MSG_HIGH); msg[1] = readl(base + SPRD_MBOX_MSG_HIGH);
id = readl(priv->outbox_base + SPRD_MBOX_ID); id = readl(base + SPRD_MBOX_ID);
chan = &priv->chan[id]; chan = &priv->chan[id];
mbox_chan_received_data(chan, (void *)msg); if (chan->cl)
mbox_chan_received_data(chan, (void *)msg);
else
dev_warn_ratelimited(priv->dev,
"message's been dropped at ch[%d]\n", id);
/* Trigger to update outbox FIFO pointer */ /* Trigger to update outbox FIFO pointer */
writel(0x1, priv->outbox_base + SPRD_MBOX_TRIGGER); writel(0x1, base + SPRD_MBOX_TRIGGER);
} }
/* Clear irq status after reading all message. */ /* Clear irq status after reading all message. */
writel(SPRD_MBOX_IRQ_CLR, priv->outbox_base + SPRD_MBOX_IRQ_STS); writel(SPRD_MBOX_IRQ_CLR, base + SPRD_MBOX_IRQ_STS);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static irqreturn_t sprd_mbox_outbox_isr(int irq, void *data)
{
struct sprd_mbox_priv *priv = data;
return do_outbox_isr(priv->outbox_base, priv);
}
static irqreturn_t sprd_mbox_supp_isr(int irq, void *data)
{
struct sprd_mbox_priv *priv = data;
return do_outbox_isr(priv->supp_base, priv);
}
static irqreturn_t sprd_mbox_inbox_isr(int irq, void *data) static irqreturn_t sprd_mbox_inbox_isr(int irq, void *data)
{ {
struct sprd_mbox_priv *priv = data; struct sprd_mbox_priv *priv = data;
...@@ -150,7 +174,7 @@ static irqreturn_t sprd_mbox_inbox_isr(int irq, void *data) ...@@ -150,7 +174,7 @@ static irqreturn_t sprd_mbox_inbox_isr(int irq, void *data)
chan = &priv->chan[id]; chan = &priv->chan[id];
/* /*
* Check if the message was fetched by remote traget, if yes, * Check if the message was fetched by remote target, if yes,
* that means the transmission has been completed. * that means the transmission has been completed.
*/ */
busy = fifo_sts & SPRD_INBOX_FIFO_BUSY_MASK; busy = fifo_sts & SPRD_INBOX_FIFO_BUSY_MASK;
...@@ -215,18 +239,30 @@ static int sprd_mbox_startup(struct mbox_chan *chan) ...@@ -215,18 +239,30 @@ static int sprd_mbox_startup(struct mbox_chan *chan)
struct sprd_mbox_priv *priv = to_sprd_mbox_priv(chan->mbox); struct sprd_mbox_priv *priv = to_sprd_mbox_priv(chan->mbox);
u32 val; u32 val;
/* Select outbox FIFO mode and reset the outbox FIFO status */ mutex_lock(&priv->lock);
writel(0x0, priv->outbox_base + SPRD_MBOX_FIFO_RST); if (priv->refcnt++ == 0) {
/* Select outbox FIFO mode and reset the outbox FIFO status */
/* Enable inbox FIFO overflow and delivery interrupt */ writel(0x0, priv->outbox_base + SPRD_MBOX_FIFO_RST);
val = readl(priv->inbox_base + SPRD_MBOX_IRQ_MSK);
val &= ~(SPRD_INBOX_FIFO_OVERFLOW_IRQ | SPRD_INBOX_FIFO_DELIVER_IRQ); /* Enable inbox FIFO overflow and delivery interrupt */
writel(val, priv->inbox_base + SPRD_MBOX_IRQ_MSK); val = readl(priv->inbox_base + SPRD_MBOX_IRQ_MSK);
val &= ~(SPRD_INBOX_FIFO_OVERFLOW_IRQ | SPRD_INBOX_FIFO_DELIVER_IRQ);
/* Enable outbox FIFO not empty interrupt */ writel(val, priv->inbox_base + SPRD_MBOX_IRQ_MSK);
val = readl(priv->outbox_base + SPRD_MBOX_IRQ_MSK);
val &= ~SPRD_OUTBOX_FIFO_NOT_EMPTY_IRQ; /* Enable outbox FIFO not empty interrupt */
writel(val, priv->outbox_base + SPRD_MBOX_IRQ_MSK); val = readl(priv->outbox_base + SPRD_MBOX_IRQ_MSK);
val &= ~SPRD_OUTBOX_FIFO_NOT_EMPTY_IRQ;
writel(val, priv->outbox_base + SPRD_MBOX_IRQ_MSK);
/* Enable supplementary outbox as the fundamental one */
if (priv->supp_base) {
writel(0x0, priv->supp_base + SPRD_MBOX_FIFO_RST);
val = readl(priv->supp_base + SPRD_MBOX_IRQ_MSK);
val &= ~SPRD_OUTBOX_FIFO_NOT_EMPTY_IRQ;
writel(val, priv->supp_base + SPRD_MBOX_IRQ_MSK);
}
}
mutex_unlock(&priv->lock);
return 0; return 0;
} }
...@@ -235,9 +271,17 @@ static void sprd_mbox_shutdown(struct mbox_chan *chan) ...@@ -235,9 +271,17 @@ static void sprd_mbox_shutdown(struct mbox_chan *chan)
{ {
struct sprd_mbox_priv *priv = to_sprd_mbox_priv(chan->mbox); struct sprd_mbox_priv *priv = to_sprd_mbox_priv(chan->mbox);
/* Disable inbox & outbox interrupt */ mutex_lock(&priv->lock);
writel(SPRD_INBOX_FIFO_IRQ_MASK, priv->inbox_base + SPRD_MBOX_IRQ_MSK); if (--priv->refcnt == 0) {
writel(SPRD_OUTBOX_FIFO_IRQ_MASK, priv->outbox_base + SPRD_MBOX_IRQ_MSK); /* Disable inbox & outbox interrupt */
writel(SPRD_INBOX_FIFO_IRQ_MASK, priv->inbox_base + SPRD_MBOX_IRQ_MSK);
writel(SPRD_OUTBOX_FIFO_IRQ_MASK, priv->outbox_base + SPRD_MBOX_IRQ_MSK);
if (priv->supp_base)
writel(SPRD_OUTBOX_FIFO_IRQ_MASK,
priv->supp_base + SPRD_MBOX_IRQ_MSK);
}
mutex_unlock(&priv->lock);
} }
static const struct mbox_chan_ops sprd_mbox_ops = { static const struct mbox_chan_ops sprd_mbox_ops = {
...@@ -258,21 +302,26 @@ static int sprd_mbox_probe(struct platform_device *pdev) ...@@ -258,21 +302,26 @@ static int sprd_mbox_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct sprd_mbox_priv *priv; struct sprd_mbox_priv *priv;
int ret, inbox_irq, outbox_irq; int ret, inbox_irq, outbox_irq, supp_irq;
unsigned long id; unsigned long id, supp;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv) if (!priv)
return -ENOMEM; return -ENOMEM;
priv->dev = dev; priv->dev = dev;
mutex_init(&priv->lock);
/* /*
* The Spreadtrum mailbox uses an inbox to send messages to the target * Unisoc mailbox uses an inbox to send messages to the target
* core, and uses an outbox to receive messages from other cores. * core, and uses (an) outbox(es) to receive messages from other
* cores.
* *
* Thus the mailbox controller supplies 2 different register addresses * Thus in general the mailbox controller supplies 2 different
* and IRQ numbers for inbox and outbox. * register addresses and IRQ numbers for inbox and outbox.
*
* If necessary, a supplementary inbox could be enabled optionally
* with an independent FIFO and an extra interrupt.
*/ */
priv->inbox_base = devm_platform_ioremap_resource(pdev, 0); priv->inbox_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(priv->inbox_base)) if (IS_ERR(priv->inbox_base))
...@@ -298,7 +347,7 @@ static int sprd_mbox_probe(struct platform_device *pdev) ...@@ -298,7 +347,7 @@ static int sprd_mbox_probe(struct platform_device *pdev)
return ret; return ret;
} }
inbox_irq = platform_get_irq(pdev, 0); inbox_irq = platform_get_irq_byname(pdev, "inbox");
if (inbox_irq < 0) if (inbox_irq < 0)
return inbox_irq; return inbox_irq;
...@@ -309,7 +358,7 @@ static int sprd_mbox_probe(struct platform_device *pdev) ...@@ -309,7 +358,7 @@ static int sprd_mbox_probe(struct platform_device *pdev)
return ret; return ret;
} }
outbox_irq = platform_get_irq(pdev, 1); outbox_irq = platform_get_irq_byname(pdev, "outbox");
if (outbox_irq < 0) if (outbox_irq < 0)
return outbox_irq; return outbox_irq;
...@@ -320,6 +369,24 @@ static int sprd_mbox_probe(struct platform_device *pdev) ...@@ -320,6 +369,24 @@ static int sprd_mbox_probe(struct platform_device *pdev)
return ret; return ret;
} }
/* Supplementary outbox IRQ is optional */
supp_irq = platform_get_irq_byname(pdev, "supp-outbox");
if (supp_irq > 0) {
ret = devm_request_irq(dev, supp_irq, sprd_mbox_supp_isr,
IRQF_NO_SUSPEND, dev_name(dev), priv);
if (ret) {
dev_err(dev, "failed to request outbox IRQ: %d\n", ret);
return ret;
}
supp = (unsigned long) of_device_get_match_data(dev);
if (!supp) {
dev_err(dev, "no supplementary outbox specified\n");
return -ENODEV;
}
priv->supp_base = priv->outbox_base + (SPRD_OUTBOX_BASE_SPAN * supp);
}
/* Get the default outbox FIFO depth */ /* Get the default outbox FIFO depth */
priv->outbox_fifo_depth = priv->outbox_fifo_depth =
readl(priv->outbox_base + SPRD_MBOX_FIFO_DEPTH) + 1; readl(priv->outbox_base + SPRD_MBOX_FIFO_DEPTH) + 1;
...@@ -342,7 +409,9 @@ static int sprd_mbox_probe(struct platform_device *pdev) ...@@ -342,7 +409,9 @@ static int sprd_mbox_probe(struct platform_device *pdev)
} }
static const struct of_device_id sprd_mbox_of_match[] = { static const struct of_device_id sprd_mbox_of_match[] = {
{ .compatible = "sprd,sc9860-mailbox", }, { .compatible = "sprd,sc9860-mailbox" },
{ .compatible = "sprd,sc9863a-mailbox",
.data = (void *)SPRD_SUPP_INBOX_ID_SC9863A },
{ }, { },
}; };
MODULE_DEVICE_TABLE(of, sprd_mbox_of_match); MODULE_DEVICE_TABLE(of, sprd_mbox_of_match);
......
...@@ -239,7 +239,7 @@ static irqreturn_t ti_msgmgr_queue_rx_interrupt(int irq, void *p) ...@@ -239,7 +239,7 @@ static irqreturn_t ti_msgmgr_queue_rx_interrupt(int irq, void *p)
/* /*
* I have no idea about the protocol being used to communicate with the * I have no idea about the protocol being used to communicate with the
* remote producer - 0 could be valid data, so I wont make a judgement * remote producer - 0 could be valid data, so I won't make a judgement
* of how many bytes I should be reading. Let the client figure this * of how many bytes I should be reading. Let the client figure this
* out.. I just read the full message and pass it on.. * out.. I just read the full message and pass it on..
*/ */
......
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