Loading drivers/mailbox/Kconfig +10 −0 Original line number Diff line number Diff line Loading @@ -132,6 +132,16 @@ config QCOM_APCS_IPC providing an interface for invoking the inter-process communication signals from the application processor to other masters. config QCOM_GVM_IPC tristate "Qualcomm Technologies, Inc. GVM IPC driver" depends on ARCH_QCOM help Say y here to enable support for the GVM IPC mailbox driver, This driver will providing an interface for invoking the communication between GVM and primary host through virtual IRQ line. It signals from the GVM to primary host and primary host will send different signal to remote sub system. config TEGRA_HSP_MBOX bool "Tegra HSP (Hardware Synchronization Primitives) Driver" depends on ARCH_TEGRA_186_SOC Loading drivers/mailbox/Makefile +2 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,8 @@ obj-$(CONFIG_BCM_FLEXRM_MBOX) += bcm-flexrm-mailbox.o obj-$(CONFIG_QCOM_APCS_IPC) += qcom-apcs-ipc-mailbox.o obj-$(CONFIG_QCOM_GVM_IPC) += qcom-gvm-ipc-mailbox.o obj-$(CONFIG_TEGRA_HSP_MBOX) += tegra-hsp.o obj-$(CONFIG_QTI_RPMH_MBOX) += qcom-rpmh-mailbox.o Loading drivers/mailbox/qcom-gvm-ipc-mailbox.c 0 → 100644 +126 −0 Original line number Diff line number Diff line /* * Copyright (c) 2020, The Linux Foundation, All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * only version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include <linux/kernel.h> #include <linux/module.h> #include <linux/io.h> #include <linux/slab.h> #include <linux/of.h> #include <linux/of_platform.h> #include <linux/platform_device.h> #include <linux/mailbox_controller.h> #define QCOM_GVM_CHNL 32 struct qcom_gvm_ipc { struct mbox_controller mbox; struct mbox_chan mbox_chans[QCOM_GVM_CHNL]; void __iomem *reg; unsigned long offset; }; static int qcom_gvm_ipc_send_data(struct mbox_chan *chan, void *data) { struct qcom_gvm_ipc *gvm_ipc = container_of(chan->mbox, struct qcom_gvm_ipc, mbox); __raw_writel(1, gvm_ipc->reg); return 0; } static const struct mbox_chan_ops qcom_gvm_ipc_ops = { .send_data = qcom_gvm_ipc_send_data, }; static int qcom_gvm_ipc_probe(struct platform_device *pdev) { struct qcom_gvm_ipc *gvm_ipc; struct resource *res; void __iomem *base; unsigned long i; int ret; gvm_ipc = devm_kzalloc(&pdev->dev, sizeof(*gvm_ipc), GFP_KERNEL); if (!gvm_ipc) return -ENOMEM; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) return -ENODEV; base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); if (IS_ERR(base)) return PTR_ERR(base); gvm_ipc->reg = base; /* Initialize channel identifiers */ for (i = 0; i < ARRAY_SIZE(gvm_ipc->mbox_chans); i++) gvm_ipc->mbox_chans[i].con_priv = (void *)i; gvm_ipc->mbox.dev = &pdev->dev; gvm_ipc->mbox.ops = &qcom_gvm_ipc_ops; gvm_ipc->mbox.chans = gvm_ipc->mbox_chans; gvm_ipc->mbox.num_chans = ARRAY_SIZE(gvm_ipc->mbox_chans); ret = mbox_controller_register(&gvm_ipc->mbox); if (ret) { dev_err(&pdev->dev, "failed to register GVM IPC controller\n"); return ret; } platform_set_drvdata(pdev, gvm_ipc); return 0; } static int qcom_gvm_ipc_remove(struct platform_device *pdev) { struct qcom_gvm_ipc *gvm_ipc = platform_get_drvdata(pdev); mbox_controller_unregister(&gvm_ipc->mbox); return 0; } /* .data is the offset of the ipc register within the global block */ static const struct of_device_id qcom_gvm_ipc_of_match[] = { { .compatible = "qcom,sm8150-apcs-hmss-global" }, {} }; MODULE_DEVICE_TABLE(of, qcom_gvm_ipc_of_match); static struct platform_driver qcom_gvm_ipc_driver = { .probe = qcom_gvm_ipc_probe, .remove = qcom_gvm_ipc_remove, .driver = { .name = "qcom_gvm_ipc", .of_match_table = qcom_gvm_ipc_of_match, .suppress_bind_attrs = true, }, }; static int __init qcom_gvm_ipc_init(void) { return platform_driver_register(&qcom_gvm_ipc_driver); } postcore_initcall(qcom_gvm_ipc_init); static void __exit qcom_gvm_ipc_exit(void) { platform_driver_unregister(&qcom_gvm_ipc_driver); } module_exit(qcom_gvm_ipc_exit); MODULE_DESCRIPTION("Qualcomm Technologies, Inc. GVM IPC driver"); MODULE_LICENSE("GPL v2"); Loading
drivers/mailbox/Kconfig +10 −0 Original line number Diff line number Diff line Loading @@ -132,6 +132,16 @@ config QCOM_APCS_IPC providing an interface for invoking the inter-process communication signals from the application processor to other masters. config QCOM_GVM_IPC tristate "Qualcomm Technologies, Inc. GVM IPC driver" depends on ARCH_QCOM help Say y here to enable support for the GVM IPC mailbox driver, This driver will providing an interface for invoking the communication between GVM and primary host through virtual IRQ line. It signals from the GVM to primary host and primary host will send different signal to remote sub system. config TEGRA_HSP_MBOX bool "Tegra HSP (Hardware Synchronization Primitives) Driver" depends on ARCH_TEGRA_186_SOC Loading
drivers/mailbox/Makefile +2 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,8 @@ obj-$(CONFIG_BCM_FLEXRM_MBOX) += bcm-flexrm-mailbox.o obj-$(CONFIG_QCOM_APCS_IPC) += qcom-apcs-ipc-mailbox.o obj-$(CONFIG_QCOM_GVM_IPC) += qcom-gvm-ipc-mailbox.o obj-$(CONFIG_TEGRA_HSP_MBOX) += tegra-hsp.o obj-$(CONFIG_QTI_RPMH_MBOX) += qcom-rpmh-mailbox.o Loading
drivers/mailbox/qcom-gvm-ipc-mailbox.c 0 → 100644 +126 −0 Original line number Diff line number Diff line /* * Copyright (c) 2020, The Linux Foundation, All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * only version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include <linux/kernel.h> #include <linux/module.h> #include <linux/io.h> #include <linux/slab.h> #include <linux/of.h> #include <linux/of_platform.h> #include <linux/platform_device.h> #include <linux/mailbox_controller.h> #define QCOM_GVM_CHNL 32 struct qcom_gvm_ipc { struct mbox_controller mbox; struct mbox_chan mbox_chans[QCOM_GVM_CHNL]; void __iomem *reg; unsigned long offset; }; static int qcom_gvm_ipc_send_data(struct mbox_chan *chan, void *data) { struct qcom_gvm_ipc *gvm_ipc = container_of(chan->mbox, struct qcom_gvm_ipc, mbox); __raw_writel(1, gvm_ipc->reg); return 0; } static const struct mbox_chan_ops qcom_gvm_ipc_ops = { .send_data = qcom_gvm_ipc_send_data, }; static int qcom_gvm_ipc_probe(struct platform_device *pdev) { struct qcom_gvm_ipc *gvm_ipc; struct resource *res; void __iomem *base; unsigned long i; int ret; gvm_ipc = devm_kzalloc(&pdev->dev, sizeof(*gvm_ipc), GFP_KERNEL); if (!gvm_ipc) return -ENOMEM; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) return -ENODEV; base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); if (IS_ERR(base)) return PTR_ERR(base); gvm_ipc->reg = base; /* Initialize channel identifiers */ for (i = 0; i < ARRAY_SIZE(gvm_ipc->mbox_chans); i++) gvm_ipc->mbox_chans[i].con_priv = (void *)i; gvm_ipc->mbox.dev = &pdev->dev; gvm_ipc->mbox.ops = &qcom_gvm_ipc_ops; gvm_ipc->mbox.chans = gvm_ipc->mbox_chans; gvm_ipc->mbox.num_chans = ARRAY_SIZE(gvm_ipc->mbox_chans); ret = mbox_controller_register(&gvm_ipc->mbox); if (ret) { dev_err(&pdev->dev, "failed to register GVM IPC controller\n"); return ret; } platform_set_drvdata(pdev, gvm_ipc); return 0; } static int qcom_gvm_ipc_remove(struct platform_device *pdev) { struct qcom_gvm_ipc *gvm_ipc = platform_get_drvdata(pdev); mbox_controller_unregister(&gvm_ipc->mbox); return 0; } /* .data is the offset of the ipc register within the global block */ static const struct of_device_id qcom_gvm_ipc_of_match[] = { { .compatible = "qcom,sm8150-apcs-hmss-global" }, {} }; MODULE_DEVICE_TABLE(of, qcom_gvm_ipc_of_match); static struct platform_driver qcom_gvm_ipc_driver = { .probe = qcom_gvm_ipc_probe, .remove = qcom_gvm_ipc_remove, .driver = { .name = "qcom_gvm_ipc", .of_match_table = qcom_gvm_ipc_of_match, .suppress_bind_attrs = true, }, }; static int __init qcom_gvm_ipc_init(void) { return platform_driver_register(&qcom_gvm_ipc_driver); } postcore_initcall(qcom_gvm_ipc_init); static void __exit qcom_gvm_ipc_exit(void) { platform_driver_unregister(&qcom_gvm_ipc_driver); } module_exit(qcom_gvm_ipc_exit); MODULE_DESCRIPTION("Qualcomm Technologies, Inc. GVM IPC driver"); MODULE_LICENSE("GPL v2");