History

Merge branch 'mailbox-for-next' of git://git.linaro.org/landing-teams/working/fujitsu/integration

Pull mailbox updates from Jassi Brar: - Minor improvement : avoid requiring unnecessary startup/shutdown callback that many drivers seem to not need - New controller driver for Qualcomm's APCS IPC * 'mailbox-for-next' of git://git.linaro.org/landing-teams/working/fujitsu/integration: mailbox: Introduce Qualcomm APCS IPC driver dt-bindings: mailbox: Introduce Qualcomm APCS global binding mailbox: Make startup and shutdown ops optional

Linus Torvalds committed 9 years ago

Commit 21c19bc2 parents b6ffe9b 25bfee15 files · +195 −6Browse files

Unified · Split

5 files
  1. Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.txt +46 −0
  2. drivers/mailbox/Kconfig +8 −0
  3. drivers/mailbox/Makefile +2 −0
  4. drivers/mailbox/mailbox.c +10 −6
  5. drivers/mailbox/qcom-apcs-ipc-mailbox.c +129 −0
Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.txt+46−0
@@ -0,0 +1,46 @@
1+Binding for the Qualcomm APCS global block
2+==========================================
3+
4+This binding describes the APCS "global" block found in various Qualcomm
5+platforms.
6+
7+- compatible:
8+ Usage: required
9+ Value type: <string>
10+ Definition: must be one of:
11+ "qcom,msm8916-apcs-kpss-global",
12+ "qcom,msm8996-apcs-hmss-global"
13+
14+- reg:
15+ Usage: required
16+ Value type: <prop-encoded-array>
17+ Definition: must specify the base address and size of the global block
18+
19+- #mbox-cells:
20+ Usage: required
21+ Value type: <u32>
22+ Definition: as described in mailbox.txt, must be 1
23+
24+
25+= EXAMPLE
26+The following example describes the APCS HMSS found in MSM8996 and part of the
27+GLINK RPM referencing the "rpm_hlos" doorbell therein.
28+
29+ apcs_glb: mailbox@9820000 {
30+ compatible = "qcom,msm8996-apcs-hmss-global";
31+ reg = <0x9820000 0x1000>;
32+
33+ #mbox-cells = <1>;
34+ };
35+
36+ rpm-glink {
37+ compatible = "qcom,glink-rpm";
38+
39+ interrupts = <GIC_SPI 168 IRQ_TYPE_EDGE_RISING>;
40+
41+ qcom,rpm-msg-ram = <&rpm_msg_ram>;
42+
43+ mboxes = <&apcs_glb 0>;
44+ mbox-names = "rpm_hlos";
45+ };
46+
drivers/mailbox/Kconfig+8−0
@@ -124,6 +124,14 @@ config MAILBOX_TEST · 123 unmodified lines
124124 Test client to help with testing new Controller driver
125125 implementations.
126126
127+config QCOM_APCS_IPC
128+ tristate "Qualcomm APCS IPC driver"
129+ depends on ARCH_QCOM || COMPILE_TEST
130+ help
131+ Say y here to enable support for the APCS IPC mailbox driver,
132+ providing an interface for invoking the inter-process communication
133+ signals from the application processor to other masters.
134+
127135 config TEGRA_HSP_MBOX
128136 bool "Tegra HSP (Hardware Synchronization Primitives) Driver"
129137 depends on ARCH_TEGRA_186_SOC
drivers/mailbox/Makefile+2−0
@@ -32,4 +32,6 @@ obj-$(CONFIG_BCM_PDC_MBOX) += bcm-pdc-mailbox.o · 31 unmodified lines
3232
3333 obj-$(CONFIG_BCM_FLEXRM_MBOX) += bcm-flexrm-mailbox.o
3434
35+obj-$(CONFIG_QCOM_APCS_IPC) += qcom-apcs-ipc-mailbox.o
36+
3537 obj-$(CONFIG_TEGRA_HSP_MBOX) += tegra-hsp.o
drivers/mailbox/mailbox.c+10−6
@@ -355,11 +355,14 @@ struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index) · 354 unmodified lines
355355
356356 spin_unlock_irqrestore(&chan->lock, flags);
357357
358− ret = chan->mbox->ops->startup(chan);
359− if (ret) {
360− dev_err(dev, "Unable to startup the chan (%d)\n", ret);
361− mbox_free_channel(chan);
362− chan = ERR_PTR(ret);
358+ if (chan->mbox->ops->startup) {
359+ ret = chan->mbox->ops->startup(chan);
360+
361+ if (ret) {
362+ dev_err(dev, "Unable to startup the chan (%d)\n", ret);
363+ mbox_free_channel(chan);
364+ chan = ERR_PTR(ret);
365+ }
363366 }
364367
365368 mutex_unlock(&con_mutex);
@@ -408,7 +411,8 @@ void mbox_free_channel(struct mbox_chan *chan) · 42 unmodified lines
408411 if (!chan || !chan->cl)
409412 return;
410413
411− chan->mbox->ops->shutdown(chan);
414+ if (chan->mbox->ops->shutdown)
415+ chan->mbox->ops->shutdown(chan);
412416
413417 /* The queued TX requests are simply aborted, no callbacks are made */
414418 spin_lock_irqsave(&chan->lock, flags);
drivers/mailbox/qcom-apcs-ipc-mailbox.c+129−0
@@ -0,0 +1,129 @@
1+/*
2+ * Copyright (c) 2017, Linaro Ltd
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License version 2 and
6+ * only version 2 as published by the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ */
13+
14+#include <linux/kernel.h>
15+#include <linux/module.h>
16+#include <linux/io.h>
17+#include <linux/slab.h>
18+#include <linux/of.h>
19+#include <linux/of_platform.h>
20+#include <linux/platform_device.h>
21+#include <linux/mailbox_controller.h>
22+
23+#define QCOM_APCS_IPC_BITS 32
24+
25+struct qcom_apcs_ipc {
26+ struct mbox_controller mbox;
27+ struct mbox_chan mbox_chans[QCOM_APCS_IPC_BITS];
28+
29+ void __iomem *reg;
30+ unsigned long offset;
31+};
32+
33+static int qcom_apcs_ipc_send_data(struct mbox_chan *chan, void *data)
34+{
35+ struct qcom_apcs_ipc *apcs = container_of(chan->mbox,
36+ struct qcom_apcs_ipc, mbox);
37+ unsigned long idx = (unsigned long)chan->con_priv;
38+
39+ writel(BIT(idx), apcs->reg);
40+
41+ return 0;
42+}
43+
44+static const struct mbox_chan_ops qcom_apcs_ipc_ops = {
45+ .send_data = qcom_apcs_ipc_send_data,
46+};
47+
48+static int qcom_apcs_ipc_probe(struct platform_device *pdev)
49+{
50+ struct qcom_apcs_ipc *apcs;
51+ struct resource *res;
52+ unsigned long offset;
53+ void __iomem *base;
54+ unsigned long i;
55+ int ret;
56+
57+ apcs = devm_kzalloc(&pdev->dev, sizeof(*apcs), GFP_KERNEL);
58+ if (!apcs)
59+ return -ENOMEM;
60+
61+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
62+ base = devm_ioremap_resource(&pdev->dev, res);
63+ if (IS_ERR(base))
64+ return PTR_ERR(base);
65+
66+ offset = (unsigned long)of_device_get_match_data(&pdev->dev);
67+
68+ apcs->reg = base + offset;
69+
70+ /* Initialize channel identifiers */
71+ for (i = 0; i < ARRAY_SIZE(apcs->mbox_chans); i++)
72+ apcs->mbox_chans[i].con_priv = (void *)i;
73+
74+ apcs->mbox.dev = &pdev->dev;
75+ apcs->mbox.ops = &qcom_apcs_ipc_ops;
76+ apcs->mbox.chans = apcs->mbox_chans;
77+ apcs->mbox.num_chans = ARRAY_SIZE(apcs->mbox_chans);
78+
79+ ret = mbox_controller_register(&apcs->mbox);
80+ if (ret) {
81+ dev_err(&pdev->dev, "failed to register APCS IPC controller\n");
82+ return ret;
83+ }
84+
85+ platform_set_drvdata(pdev, apcs);
86+
87+ return 0;
88+}
89+
90+static int qcom_apcs_ipc_remove(struct platform_device *pdev)
91+{
92+ struct qcom_apcs_ipc *apcs = platform_get_drvdata(pdev);
93+
94+ mbox_controller_unregister(&apcs->mbox);
95+
96+ return 0;
97+}
98+
99+/* .data is the offset of the ipc register within the global block */
100+static const struct of_device_id qcom_apcs_ipc_of_match[] = {
101+ { .compatible = "qcom,msm8916-apcs-kpss-global", .data = (void *)8 },
102+ { .compatible = "qcom,msm8996-apcs-hmss-global", .data = (void *)16 },
103+ {}
104+};
105+MODULE_DEVICE_TABLE(of, qcom_apcs_ipc_of_match);
106+
107+static struct platform_driver qcom_apcs_ipc_driver = {
108+ .probe = qcom_apcs_ipc_probe,
109+ .remove = qcom_apcs_ipc_remove,
110+ .driver = {
111+ .name = "qcom_apcs_ipc",
112+ .of_match_table = qcom_apcs_ipc_of_match,
113+ },
114+};
115+
116+static int __init qcom_apcs_ipc_init(void)
117+{
118+ return platform_driver_register(&qcom_apcs_ipc_driver);
119+}
120+postcore_initcall(qcom_apcs_ipc_init);
121+
122+static void __exit qcom_apcs_ipc_exit(void)
123+{
124+ platform_driver_unregister(&qcom_apcs_ipc_driver);
125+}
126+module_exit(qcom_apcs_ipc_exit);
127+
128+MODULE_LICENSE("GPL v2");
129+MODULE_DESCRIPTION("Qualcomm APCS IPC driver");