Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

+195 -6
+46
Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.txt
··· 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 +
+8
drivers/mailbox/Kconfig
··· 124 124 Test client to help with testing new Controller driver 125 125 implementations. 126 126 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 + 127 135 config TEGRA_HSP_MBOX 128 136 bool "Tegra HSP (Hardware Synchronization Primitives) Driver" 129 137 depends on ARCH_TEGRA_186_SOC
+2
drivers/mailbox/Makefile
··· 32 32 33 33 obj-$(CONFIG_BCM_FLEXRM_MBOX) += bcm-flexrm-mailbox.o 34 34 35 + obj-$(CONFIG_QCOM_APCS_IPC) += qcom-apcs-ipc-mailbox.o 36 + 35 37 obj-$(CONFIG_TEGRA_HSP_MBOX) += tegra-hsp.o
+10 -6
drivers/mailbox/mailbox.c
··· 355 355 356 356 spin_unlock_irqrestore(&chan->lock, flags); 357 357 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 + } 363 366 } 364 367 365 368 mutex_unlock(&con_mutex); ··· 411 408 if (!chan || !chan->cl) 412 409 return; 413 410 414 - chan->mbox->ops->shutdown(chan); 411 + if (chan->mbox->ops->shutdown) 412 + chan->mbox->ops->shutdown(chan); 415 413 416 414 /* The queued TX requests are simply aborted, no callbacks are made */ 417 415 spin_lock_irqsave(&chan->lock, flags);
+129
drivers/mailbox/qcom-apcs-ipc-mailbox.c
··· 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");