aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-04-06 20:20:14 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-04-06 20:20:14 -0400
commit28da7be5ebc096ada5e6bc526c623bdd8c47800a (patch)
tree0714d6ca447818cc1aa348ae538ed18a901512df
parent9eda2d2dca830f0f8923b1f377d0fb70f576af1d (diff)
parent41c0e939d70ddb6860e340e7532df8984783f867 (diff)
Merge tag 'mailbox-v4.17' of git://git.linaro.org/landing-teams/working/fujitsu/integration
Pull mailbox updates from Jassi Brar: - New Hi3660 mailbox driver - Fix TEGRA Kconfig warning - Broadcom: use dma_pool_zalloc instead of dma_pool_alloc+memset * tag 'mailbox-v4.17' of git://git.linaro.org/landing-teams/working/fujitsu/integration: mailbox: Add support for Hi3660 mailbox dt-bindings: mailbox: Introduce Hi3660 controller binding mailbox: tegra: relax TEGRA_HSP_MBOX Kconfig dependencies maillbox: bcm-flexrm-mailbox: Use dma_pool_zalloc()
-rw-r--r--Documentation/devicetree/bindings/mailbox/hisilicon,hi3660-mailbox.txt51
-rw-r--r--drivers/mailbox/Kconfig10
-rw-r--r--drivers/mailbox/Makefile2
-rw-r--r--drivers/mailbox/bcm-flexrm-mailbox.c3
-rw-r--r--drivers/mailbox/hi3660-mailbox.c312
5 files changed, 375 insertions, 3 deletions
diff --git a/Documentation/devicetree/bindings/mailbox/hisilicon,hi3660-mailbox.txt b/Documentation/devicetree/bindings/mailbox/hisilicon,hi3660-mailbox.txt
new file mode 100644
index 000000000000..3e5b4537407d
--- /dev/null
+++ b/Documentation/devicetree/bindings/mailbox/hisilicon,hi3660-mailbox.txt
@@ -0,0 +1,51 @@
1Hisilicon Hi3660 Mailbox Controller
2
3Hisilicon Hi3660 mailbox controller supports up to 32 channels. Messages
4are passed between processors, including application & communication
5processors, MCU, HIFI, etc. Each channel is unidirectional and accessed
6by using MMIO registers; it supports maximum to 8 words message.
7
8Controller
9----------
10
11Required properties:
12- compatible: : Shall be "hisilicon,hi3660-mbox"
13- reg: : Offset and length of the device's register set
14- #mbox-cells: : Must be 3
15 <&phandle channel dst_irq ack_irq>
16 phandle : Label name of controller
17 channel : Channel number
18 dst_irq : Remote interrupt vector
19 ack_irq : Local interrupt vector
20
21- interrupts: : Contains the two IRQ lines for mailbox.
22
23Example:
24
25mailbox: mailbox@e896b000 {
26 compatible = "hisilicon,hi3660-mbox";
27 reg = <0x0 0xe896b000 0x0 0x1000>;
28 interrupts = <0x0 0xc0 0x4>,
29 <0x0 0xc1 0x4>;
30 #mbox-cells = <3>;
31};
32
33Client
34------
35
36Required properties:
37- compatible : See the client docs
38- mboxes : Standard property to specify a Mailbox (See ./mailbox.txt)
39 Cells must match 'mbox-cells' (See Controller docs above)
40
41Optional properties
42- mbox-names : Name given to channels seen in the 'mboxes' property.
43
44Example:
45
46stub_clock: stub_clock@e896b500 {
47 compatible = "hisilicon,hi3660-stub-clk";
48 reg = <0x0 0xe896b500 0x0 0x0100>;
49 #clock-cells = <1>;
50 mboxes = <&mailbox 13 3 0>;
51};
diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
index ba2f1525f4ee..a2bb27446dce 100644
--- a/drivers/mailbox/Kconfig
+++ b/drivers/mailbox/Kconfig
@@ -108,6 +108,14 @@ config TI_MESSAGE_MANAGER
108 multiple processors within the SoC. Select this driver if your 108 multiple processors within the SoC. Select this driver if your
109 platform has support for the hardware block. 109 platform has support for the hardware block.
110 110
111config HI3660_MBOX
112 tristate "Hi3660 Mailbox"
113 depends on ARCH_HISI && OF
114 help
115 An implementation of the hi3660 mailbox. It is used to send message
116 between application processors and other processors/MCU/DSP. Select
117 Y here if you want to use Hi3660 mailbox controller.
118
111config HI6220_MBOX 119config HI6220_MBOX
112 tristate "Hi6220 Mailbox" 120 tristate "Hi6220 Mailbox"
113 depends on ARCH_HISI 121 depends on ARCH_HISI
@@ -134,7 +142,7 @@ config QCOM_APCS_IPC
134 142
135config TEGRA_HSP_MBOX 143config TEGRA_HSP_MBOX
136 bool "Tegra HSP (Hardware Synchronization Primitives) Driver" 144 bool "Tegra HSP (Hardware Synchronization Primitives) Driver"
137 depends on ARCH_TEGRA_186_SOC 145 depends on ARCH_TEGRA
138 help 146 help
139 The Tegra HSP driver is used for the interprocessor communication 147 The Tegra HSP driver is used for the interprocessor communication
140 between different remote processors and host processors on Tegra186 148 between different remote processors and host processors on Tegra186
diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
index 4896f8dcae95..cc23c3a43fcd 100644
--- a/drivers/mailbox/Makefile
+++ b/drivers/mailbox/Makefile
@@ -27,6 +27,8 @@ obj-$(CONFIG_TI_MESSAGE_MANAGER) += ti-msgmgr.o
27 27
28obj-$(CONFIG_XGENE_SLIMPRO_MBOX) += mailbox-xgene-slimpro.o 28obj-$(CONFIG_XGENE_SLIMPRO_MBOX) += mailbox-xgene-slimpro.o
29 29
30obj-$(CONFIG_HI3660_MBOX) += hi3660-mailbox.o
31
30obj-$(CONFIG_HI6220_MBOX) += hi6220-mailbox.o 32obj-$(CONFIG_HI6220_MBOX) += hi6220-mailbox.o
31 33
32obj-$(CONFIG_BCM_PDC_MBOX) += bcm-pdc-mailbox.o 34obj-$(CONFIG_BCM_PDC_MBOX) += bcm-pdc-mailbox.o
diff --git a/drivers/mailbox/bcm-flexrm-mailbox.c b/drivers/mailbox/bcm-flexrm-mailbox.c
index a8cf4333a68f..8ab077ff58f4 100644
--- a/drivers/mailbox/bcm-flexrm-mailbox.c
+++ b/drivers/mailbox/bcm-flexrm-mailbox.c
@@ -1268,7 +1268,7 @@ static int flexrm_startup(struct mbox_chan *chan)
1268 } 1268 }
1269 1269
1270 /* Allocate completion memory */ 1270 /* Allocate completion memory */
1271 ring->cmpl_base = dma_pool_alloc(ring->mbox->cmpl_pool, 1271 ring->cmpl_base = dma_pool_zalloc(ring->mbox->cmpl_pool,
1272 GFP_KERNEL, &ring->cmpl_dma_base); 1272 GFP_KERNEL, &ring->cmpl_dma_base);
1273 if (!ring->cmpl_base) { 1273 if (!ring->cmpl_base) {
1274 dev_err(ring->mbox->dev, 1274 dev_err(ring->mbox->dev,
@@ -1277,7 +1277,6 @@ static int flexrm_startup(struct mbox_chan *chan)
1277 ret = -ENOMEM; 1277 ret = -ENOMEM;
1278 goto fail_free_bd_memory; 1278 goto fail_free_bd_memory;
1279 } 1279 }
1280 memset(ring->cmpl_base, 0, RING_CMPL_SIZE);
1281 1280
1282 /* Request IRQ */ 1281 /* Request IRQ */
1283 if (ring->irq == UINT_MAX) { 1282 if (ring->irq == UINT_MAX) {
diff --git a/drivers/mailbox/hi3660-mailbox.c b/drivers/mailbox/hi3660-mailbox.c
new file mode 100644
index 000000000000..3eea6b642484
--- /dev/null
+++ b/drivers/mailbox/hi3660-mailbox.c
@@ -0,0 +1,312 @@
1// SPDX-License-Identifier: GPL-2.0
2// Copyright (c) 2017-2018 Hisilicon Limited.
3// Copyright (c) 2017-2018 Linaro Limited.
4
5#include <linux/bitops.h>
6#include <linux/delay.h>
7#include <linux/device.h>
8#include <linux/err.h>
9#include <linux/interrupt.h>
10#include <linux/io.h>
11#include <linux/iopoll.h>
12#include <linux/mailbox_controller.h>
13#include <linux/module.h>
14#include <linux/platform_device.h>
15#include <linux/slab.h>
16
17#include "mailbox.h"
18
19#define MBOX_CHAN_MAX 32
20
21#define MBOX_RX 0x0
22#define MBOX_TX 0x1
23
24#define MBOX_BASE(mbox, ch) ((mbox)->base + ((ch) * 0x40))
25#define MBOX_SRC_REG 0x00
26#define MBOX_DST_REG 0x04
27#define MBOX_DCLR_REG 0x08
28#define MBOX_DSTAT_REG 0x0c
29#define MBOX_MODE_REG 0x10
30#define MBOX_IMASK_REG 0x14
31#define MBOX_ICLR_REG 0x18
32#define MBOX_SEND_REG 0x1c
33#define MBOX_DATA_REG 0x20
34
35#define MBOX_IPC_LOCK_REG 0xa00
36#define MBOX_IPC_UNLOCK 0x1acce551
37
38#define MBOX_AUTOMATIC_ACK 1
39
40#define MBOX_STATE_IDLE BIT(4)
41#define MBOX_STATE_ACK BIT(7)
42
43#define MBOX_MSG_LEN 8
44
45/**
46 * Hi3660 mailbox channel information
47 *
48 * A channel can be used for TX or RX, it can trigger remote
49 * processor interrupt to notify remote processor and can receive
50 * interrupt if has incoming message.
51 *
52 * @dst_irq: Interrupt vector for remote processor
53 * @ack_irq: Interrupt vector for local processor
54 */
55struct hi3660_chan_info {
56 unsigned int dst_irq;
57 unsigned int ack_irq;
58};
59
60/**
61 * Hi3660 mailbox controller data
62 *
63 * Mailbox controller includes 32 channels and can allocate
64 * channel for message transferring.
65 *
66 * @dev: Device to which it is attached
67 * @base: Base address of the register mapping region
68 * @chan: Representation of channels in mailbox controller
69 * @mchan: Representation of channel info
70 * @controller: Representation of a communication channel controller
71 */
72struct hi3660_mbox {
73 struct device *dev;
74 void __iomem *base;
75 struct mbox_chan chan[MBOX_CHAN_MAX];
76 struct hi3660_chan_info mchan[MBOX_CHAN_MAX];
77 struct mbox_controller controller;
78};
79
80static struct hi3660_mbox *to_hi3660_mbox(struct mbox_controller *mbox)
81{
82 return container_of(mbox, struct hi3660_mbox, controller);
83}
84
85static int hi3660_mbox_check_state(struct mbox_chan *chan)
86{
87 unsigned long ch = (unsigned long)chan->con_priv;
88 struct hi3660_mbox *mbox = to_hi3660_mbox(chan->mbox);
89 struct hi3660_chan_info *mchan = &mbox->mchan[ch];
90 void __iomem *base = MBOX_BASE(mbox, ch);
91 unsigned long val;
92 unsigned int ret;
93
94 /* Mailbox is idle so directly bail out */
95 if (readl(base + MBOX_MODE_REG) & MBOX_STATE_IDLE)
96 return 0;
97
98 /* Wait for acknowledge from remote */
99 ret = readx_poll_timeout_atomic(readl, base + MBOX_MODE_REG,
100 val, (val & MBOX_STATE_ACK), 1000, 300000);
101 if (ret) {
102 dev_err(mbox->dev, "%s: timeout for receiving ack\n", __func__);
103 return ret;
104 }
105
106 /* Ensure channel is released */
107 writel(0xffffffff, base + MBOX_IMASK_REG);
108 writel(BIT(mchan->ack_irq), base + MBOX_SRC_REG);
109 return 0;
110}
111
112static int hi3660_mbox_unlock(struct mbox_chan *chan)
113{
114 struct hi3660_mbox *mbox = to_hi3660_mbox(chan->mbox);
115 unsigned int val, retry = 3;
116
117 do {
118 writel(MBOX_IPC_UNLOCK, mbox->base + MBOX_IPC_LOCK_REG);
119
120 val = readl(mbox->base + MBOX_IPC_LOCK_REG);
121 if (!val)
122 break;
123
124 udelay(10);
125 } while (retry--);
126
127 if (val)
128 dev_err(mbox->dev, "%s: failed to unlock mailbox\n", __func__);
129
130 return (!val) ? 0 : -ETIMEDOUT;
131}
132
133static int hi3660_mbox_acquire_channel(struct mbox_chan *chan)
134{
135 unsigned long ch = (unsigned long)chan->con_priv;
136 struct hi3660_mbox *mbox = to_hi3660_mbox(chan->mbox);
137 struct hi3660_chan_info *mchan = &mbox->mchan[ch];
138 void __iomem *base = MBOX_BASE(mbox, ch);
139 unsigned int val, retry;
140
141 for (retry = 10; retry; retry--) {
142 /* Check if channel is in idle state */
143 if (readl(base + MBOX_MODE_REG) & MBOX_STATE_IDLE) {
144 writel(BIT(mchan->ack_irq), base + MBOX_SRC_REG);
145
146 /* Check ack bit has been set successfully */
147 val = readl(base + MBOX_SRC_REG);
148 if (val & BIT(mchan->ack_irq))
149 break;
150 }
151 }
152
153 if (!retry)
154 dev_err(mbox->dev, "%s: failed to acquire channel\n", __func__);
155
156 return retry ? 0 : -ETIMEDOUT;
157}
158
159static int hi3660_mbox_startup(struct mbox_chan *chan)
160{
161 int ret;
162
163 ret = hi3660_mbox_check_state(chan);
164 if (ret)
165 return ret;
166
167 ret = hi3660_mbox_unlock(chan);
168 if (ret)
169 return ret;
170
171 ret = hi3660_mbox_acquire_channel(chan);
172 if (ret)
173 return ret;
174
175 return 0;
176}
177
178static int hi3660_mbox_send_data(struct mbox_chan *chan, void *msg)
179{
180 unsigned long ch = (unsigned long)chan->con_priv;
181 struct hi3660_mbox *mbox = to_hi3660_mbox(chan->mbox);
182 struct hi3660_chan_info *mchan = &mbox->mchan[ch];
183 void __iomem *base = MBOX_BASE(mbox, ch);
184 u32 *buf = msg;
185 unsigned int i;
186
187 /* Ensure channel is released */
188 writel_relaxed(0xffffffff, base + MBOX_IMASK_REG);
189 writel_relaxed(BIT(mchan->ack_irq), base + MBOX_SRC_REG);
190
191 /* Clear mask for destination interrupt */
192 writel_relaxed(~BIT(mchan->dst_irq), base + MBOX_IMASK_REG);
193
194 /* Config destination for interrupt vector */
195 writel_relaxed(BIT(mchan->dst_irq), base + MBOX_DST_REG);
196
197 /* Automatic acknowledge mode */
198 writel_relaxed(MBOX_AUTOMATIC_ACK, base + MBOX_MODE_REG);
199
200 /* Fill message data */
201 for (i = 0; i < MBOX_MSG_LEN; i++)
202 writel_relaxed(buf[i], base + MBOX_DATA_REG + i * 4);
203
204 /* Trigger data transferring */
205 writel(BIT(mchan->ack_irq), base + MBOX_SEND_REG);
206 return 0;
207}
208
209static struct mbox_chan_ops hi3660_mbox_ops = {
210 .startup = hi3660_mbox_startup,
211 .send_data = hi3660_mbox_send_data,
212};
213
214static struct mbox_chan *hi3660_mbox_xlate(struct mbox_controller *controller,
215 const struct of_phandle_args *spec)
216{
217 struct hi3660_mbox *mbox = to_hi3660_mbox(controller);
218 struct hi3660_chan_info *mchan;
219 unsigned int ch = spec->args[0];
220
221 if (ch >= MBOX_CHAN_MAX) {
222 dev_err(mbox->dev, "Invalid channel idx %d\n", ch);
223 return ERR_PTR(-EINVAL);
224 }
225
226 mchan = &mbox->mchan[ch];
227 mchan->dst_irq = spec->args[1];
228 mchan->ack_irq = spec->args[2];
229
230 return &mbox->chan[ch];
231}
232
233static const struct of_device_id hi3660_mbox_of_match[] = {
234 { .compatible = "hisilicon,hi3660-mbox", },
235 {},
236};
237
238MODULE_DEVICE_TABLE(of, hi3660_mbox_of_match);
239
240static int hi3660_mbox_probe(struct platform_device *pdev)
241{
242 struct device *dev = &pdev->dev;
243 struct hi3660_mbox *mbox;
244 struct mbox_chan *chan;
245 struct resource *res;
246 unsigned long ch;
247 int err;
248
249 mbox = devm_kzalloc(dev, sizeof(*mbox), GFP_KERNEL);
250 if (!mbox)
251 return -ENOMEM;
252
253 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
254 mbox->base = devm_ioremap_resource(dev, res);
255 if (IS_ERR(mbox->base))
256 return PTR_ERR(mbox->base);
257
258 mbox->dev = dev;
259 mbox->controller.dev = dev;
260 mbox->controller.chans = mbox->chan;
261 mbox->controller.num_chans = MBOX_CHAN_MAX;
262 mbox->controller.ops = &hi3660_mbox_ops;
263 mbox->controller.of_xlate = hi3660_mbox_xlate;
264
265 /* Initialize mailbox channel data */
266 chan = mbox->chan;
267 for (ch = 0; ch < MBOX_CHAN_MAX; ch++)
268 chan[ch].con_priv = (void *)ch;
269
270 err = mbox_controller_register(&mbox->controller);
271 if (err) {
272 dev_err(dev, "Failed to register mailbox %d\n", err);
273 return err;
274 }
275
276 platform_set_drvdata(pdev, mbox);
277 dev_info(dev, "Mailbox enabled\n");
278 return 0;
279}
280
281static int hi3660_mbox_remove(struct platform_device *pdev)
282{
283 struct hi3660_mbox *mbox = platform_get_drvdata(pdev);
284
285 mbox_controller_unregister(&mbox->controller);
286 return 0;
287}
288
289static struct platform_driver hi3660_mbox_driver = {
290 .probe = hi3660_mbox_probe,
291 .remove = hi3660_mbox_remove,
292 .driver = {
293 .name = "hi3660-mbox",
294 .of_match_table = hi3660_mbox_of_match,
295 },
296};
297
298static int __init hi3660_mbox_init(void)
299{
300 return platform_driver_register(&hi3660_mbox_driver);
301}
302core_initcall(hi3660_mbox_init);
303
304static void __exit hi3660_mbox_exit(void)
305{
306 platform_driver_unregister(&hi3660_mbox_driver);
307}
308module_exit(hi3660_mbox_exit);
309
310MODULE_LICENSE("GPL");
311MODULE_DESCRIPTION("Hisilicon Hi3660 Mailbox Controller");
312MODULE_AUTHOR("Leo Yan <leo.yan@linaro.org>");