summaryrefslogtreecommitdiffstats
path: root/drivers/rpmsg
diff options
context:
space:
mode:
authorBjorn Andersson <bjorn.andersson@linaro.org>2018-04-19 21:17:57 -0400
committerBjorn Andersson <bjorn.andersson@linaro.org>2018-04-25 20:09:57 -0400
commitab460a2e72dabecfdabd45eb7e3ee2d73fc876d4 (patch)
treeec9636cc02aa76deba9f9c8a1dcd21581119f636 /drivers/rpmsg
parent39e47767ec9b22f844c2a07c9d329256960d4021 (diff)
rpmsg: qcom_smd: Access APCS through mailbox framework
Attempt to acquire the APCS IPC through the mailbox framework and fall back to the old syscon based approach, to allow us to move away from using the syscon. Reviewed-by: Arun Kumar Neelakantam <aneela@codeaurora.org> Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Diffstat (limited to 'drivers/rpmsg')
-rw-r--r--drivers/rpmsg/Kconfig1
-rw-r--r--drivers/rpmsg/qcom_smd.c68
2 files changed, 50 insertions, 19 deletions
diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig
index 65a9f6b892f0..9b14090e3603 100644
--- a/drivers/rpmsg/Kconfig
+++ b/drivers/rpmsg/Kconfig
@@ -39,6 +39,7 @@ config RPMSG_QCOM_GLINK_SMEM
39 39
40config RPMSG_QCOM_SMD 40config RPMSG_QCOM_SMD
41 tristate "Qualcomm Shared Memory Driver (SMD)" 41 tristate "Qualcomm Shared Memory Driver (SMD)"
42 depends on MAILBOX
42 depends on QCOM_SMEM 43 depends on QCOM_SMEM
43 select RPMSG 44 select RPMSG
44 help 45 help
diff --git a/drivers/rpmsg/qcom_smd.c b/drivers/rpmsg/qcom_smd.c
index 5ce9bf7b897d..b07e9a1a9d22 100644
--- a/drivers/rpmsg/qcom_smd.c
+++ b/drivers/rpmsg/qcom_smd.c
@@ -14,6 +14,7 @@
14 14
15#include <linux/interrupt.h> 15#include <linux/interrupt.h>
16#include <linux/io.h> 16#include <linux/io.h>
17#include <linux/mailbox_client.h>
17#include <linux/mfd/syscon.h> 18#include <linux/mfd/syscon.h>
18#include <linux/module.h> 19#include <linux/module.h>
19#include <linux/of_irq.h> 20#include <linux/of_irq.h>
@@ -107,6 +108,8 @@ static const struct {
107 * @ipc_regmap: regmap handle holding the outgoing ipc register 108 * @ipc_regmap: regmap handle holding the outgoing ipc register
108 * @ipc_offset: offset within @ipc_regmap of the register for ipc 109 * @ipc_offset: offset within @ipc_regmap of the register for ipc
109 * @ipc_bit: bit in the register at @ipc_offset of @ipc_regmap 110 * @ipc_bit: bit in the register at @ipc_offset of @ipc_regmap
111 * @mbox_client: mailbox client handle
112 * @mbox_chan: apcs ipc mailbox channel handle
110 * @channels: list of all channels detected on this edge 113 * @channels: list of all channels detected on this edge
111 * @channels_lock: guard for modifications of @channels 114 * @channels_lock: guard for modifications of @channels
112 * @allocated: array of bitmaps representing already allocated channels 115 * @allocated: array of bitmaps representing already allocated channels
@@ -129,6 +132,9 @@ struct qcom_smd_edge {
129 int ipc_offset; 132 int ipc_offset;
130 int ipc_bit; 133 int ipc_bit;
131 134
135 struct mbox_client mbox_client;
136 struct mbox_chan *mbox_chan;
137
132 struct list_head channels; 138 struct list_head channels;
133 spinlock_t channels_lock; 139 spinlock_t channels_lock;
134 140
@@ -366,7 +372,17 @@ static void qcom_smd_signal_channel(struct qcom_smd_channel *channel)
366{ 372{
367 struct qcom_smd_edge *edge = channel->edge; 373 struct qcom_smd_edge *edge = channel->edge;
368 374
369 regmap_write(edge->ipc_regmap, edge->ipc_offset, BIT(edge->ipc_bit)); 375 if (edge->mbox_chan) {
376 /*
377 * We can ignore a failing mbox_send_message() as the only
378 * possible cause is that the FIFO in the framework is full of
379 * other writes to the same bit.
380 */
381 mbox_send_message(edge->mbox_chan, NULL);
382 mbox_client_txdone(edge->mbox_chan, 0);
383 } else {
384 regmap_write(edge->ipc_regmap, edge->ipc_offset, BIT(edge->ipc_bit));
385 }
370} 386}
371 387
372/* 388/*
@@ -1326,27 +1342,37 @@ static int qcom_smd_parse_edge(struct device *dev,
1326 key = "qcom,remote-pid"; 1342 key = "qcom,remote-pid";
1327 of_property_read_u32(node, key, &edge->remote_pid); 1343 of_property_read_u32(node, key, &edge->remote_pid);
1328 1344
1329 syscon_np = of_parse_phandle(node, "qcom,ipc", 0); 1345 edge->mbox_client.dev = dev;
1330 if (!syscon_np) { 1346 edge->mbox_client.knows_txdone = true;
1331 dev_err(dev, "no qcom,ipc node\n"); 1347 edge->mbox_chan = mbox_request_channel(&edge->mbox_client, 0);
1332 return -ENODEV; 1348 if (IS_ERR(edge->mbox_chan)) {
1333 } 1349 if (PTR_ERR(edge->mbox_chan) != -ENODEV)
1350 return PTR_ERR(edge->mbox_chan);
1334 1351
1335 edge->ipc_regmap = syscon_node_to_regmap(syscon_np); 1352 edge->mbox_chan = NULL;
1336 if (IS_ERR(edge->ipc_regmap))
1337 return PTR_ERR(edge->ipc_regmap);
1338 1353
1339 key = "qcom,ipc"; 1354 syscon_np = of_parse_phandle(node, "qcom,ipc", 0);
1340 ret = of_property_read_u32_index(node, key, 1, &edge->ipc_offset); 1355 if (!syscon_np) {
1341 if (ret < 0) { 1356 dev_err(dev, "no qcom,ipc node\n");
1342 dev_err(dev, "no offset in %s\n", key); 1357 return -ENODEV;
1343 return -EINVAL; 1358 }
1344 }
1345 1359
1346 ret = of_property_read_u32_index(node, key, 2, &edge->ipc_bit); 1360 edge->ipc_regmap = syscon_node_to_regmap(syscon_np);
1347 if (ret < 0) { 1361 if (IS_ERR(edge->ipc_regmap))
1348 dev_err(dev, "no bit in %s\n", key); 1362 return PTR_ERR(edge->ipc_regmap);
1349 return -EINVAL; 1363
1364 key = "qcom,ipc";
1365 ret = of_property_read_u32_index(node, key, 1, &edge->ipc_offset);
1366 if (ret < 0) {
1367 dev_err(dev, "no offset in %s\n", key);
1368 return -EINVAL;
1369 }
1370
1371 ret = of_property_read_u32_index(node, key, 2, &edge->ipc_bit);
1372 if (ret < 0) {
1373 dev_err(dev, "no bit in %s\n", key);
1374 return -EINVAL;
1375 }
1350 } 1376 }
1351 1377
1352 ret = of_property_read_string(node, "label", &edge->name); 1378 ret = of_property_read_string(node, "label", &edge->name);
@@ -1453,6 +1479,9 @@ struct qcom_smd_edge *qcom_smd_register_edge(struct device *parent,
1453 return edge; 1479 return edge;
1454 1480
1455unregister_dev: 1481unregister_dev:
1482 if (!IS_ERR_OR_NULL(edge->mbox_chan))
1483 mbox_free_channel(edge->mbox_chan);
1484
1456 device_unregister(&edge->dev); 1485 device_unregister(&edge->dev);
1457 return ERR_PTR(ret); 1486 return ERR_PTR(ret);
1458} 1487}
@@ -1481,6 +1510,7 @@ int qcom_smd_unregister_edge(struct qcom_smd_edge *edge)
1481 if (ret) 1510 if (ret)
1482 dev_warn(&edge->dev, "can't remove smd device: %d\n", ret); 1511 dev_warn(&edge->dev, "can't remove smd device: %d\n", ret);
1483 1512
1513 mbox_free_channel(edge->mbox_chan);
1484 device_unregister(&edge->dev); 1514 device_unregister(&edge->dev);
1485 1515
1486 return 0; 1516 return 0;