blob: 9325d2abc745baf8155ec7eaacaa71b390022568 [file] [log] [blame]
Thomas Gleixner97fb5e82019-05-29 07:17:58 -07001// SPDX-License-Identifier: GPL-2.0-only
Bjorn Andersson25bfee12017-05-27 16:14:04 -07002/*
3 * Copyright (c) 2017, Linaro Ltd
Bjorn Andersson25bfee12017-05-27 16:14:04 -07004 */
5
6#include <linux/kernel.h>
7#include <linux/module.h>
8#include <linux/io.h>
9#include <linux/slab.h>
10#include <linux/of.h>
11#include <linux/of_platform.h>
12#include <linux/platform_device.h>
Georgi Djakovc6a8b172017-12-05 17:46:56 +020013#include <linux/regmap.h>
Bjorn Andersson25bfee12017-05-27 16:14:04 -070014#include <linux/mailbox_controller.h>
15
16#define QCOM_APCS_IPC_BITS 32
17
18struct qcom_apcs_ipc {
19 struct mbox_controller mbox;
20 struct mbox_chan mbox_chans[QCOM_APCS_IPC_BITS];
21
Georgi Djakovc6a8b172017-12-05 17:46:56 +020022 struct regmap *regmap;
Bjorn Andersson25bfee12017-05-27 16:14:04 -070023 unsigned long offset;
Georgi Djakovc815d762017-12-05 17:46:57 +020024 struct platform_device *clk;
Bjorn Andersson25bfee12017-05-27 16:14:04 -070025};
26
Sivaprakash Murugesan9b007932020-06-08 15:07:26 +053027struct qcom_apcs_ipc_data {
28 int offset;
29 char *clk_name;
30};
31
Sivaprakash Murugesane9f901d2020-06-08 15:07:27 +053032static const struct qcom_apcs_ipc_data ipq6018_apcs_data = {
33 .offset = 8, .clk_name = "qcom,apss-ipq6018-clk"
34};
35
Sivaprakash Murugesan9b007932020-06-08 15:07:26 +053036static const struct qcom_apcs_ipc_data msm8916_apcs_data = {
37 .offset = 8, .clk_name = "qcom-apcs-msm8916-clk"
38};
39
Konrad Dybciodde68052020-06-24 17:01:03 +020040static const struct qcom_apcs_ipc_data msm8994_apcs_data = {
41 .offset = 8, .clk_name = NULL
42};
43
Sivaprakash Murugesan9b007932020-06-08 15:07:26 +053044static const struct qcom_apcs_ipc_data msm8996_apcs_data = {
45 .offset = 16, .clk_name = NULL
46};
47
Sivaprakash Murugesan9b007932020-06-08 15:07:26 +053048static const struct qcom_apcs_ipc_data apps_shared_apcs_data = {
49 .offset = 12, .clk_name = NULL
50};
51
Manivannan Sadhasivamc319f782021-01-18 09:41:53 +053052static const struct qcom_apcs_ipc_data sdx55_apcs_data = {
53 .offset = 0x1008, .clk_name = "qcom-sdx55-acps-clk"
54};
55
Georgi Djakovc6a8b172017-12-05 17:46:56 +020056static const struct regmap_config apcs_regmap_config = {
57 .reg_bits = 32,
58 .reg_stride = 4,
59 .val_bits = 32,
Manivannan Sadhasivamc319f782021-01-18 09:41:53 +053060 .max_register = 0x1008,
Georgi Djakovc6a8b172017-12-05 17:46:56 +020061 .fast_io = true,
62};
63
Bjorn Andersson25bfee12017-05-27 16:14:04 -070064static int qcom_apcs_ipc_send_data(struct mbox_chan *chan, void *data)
65{
66 struct qcom_apcs_ipc *apcs = container_of(chan->mbox,
67 struct qcom_apcs_ipc, mbox);
68 unsigned long idx = (unsigned long)chan->con_priv;
69
Georgi Djakovc6a8b172017-12-05 17:46:56 +020070 return regmap_write(apcs->regmap, apcs->offset, BIT(idx));
Bjorn Andersson25bfee12017-05-27 16:14:04 -070071}
72
73static const struct mbox_chan_ops qcom_apcs_ipc_ops = {
74 .send_data = qcom_apcs_ipc_send_data,
75};
76
77static int qcom_apcs_ipc_probe(struct platform_device *pdev)
78{
79 struct qcom_apcs_ipc *apcs;
Sivaprakash Murugesan9b007932020-06-08 15:07:26 +053080 const struct qcom_apcs_ipc_data *apcs_data;
Georgi Djakovc6a8b172017-12-05 17:46:56 +020081 struct regmap *regmap;
Bjorn Andersson25bfee12017-05-27 16:14:04 -070082 void __iomem *base;
83 unsigned long i;
84 int ret;
85
86 apcs = devm_kzalloc(&pdev->dev, sizeof(*apcs), GFP_KERNEL);
87 if (!apcs)
88 return -ENOMEM;
89
Cai Huoqing78c67982021-09-07 15:41:39 +080090 base = devm_platform_ioremap_resource(pdev, 0);
Bjorn Andersson25bfee12017-05-27 16:14:04 -070091 if (IS_ERR(base))
92 return PTR_ERR(base);
93
Georgi Djakovc6a8b172017-12-05 17:46:56 +020094 regmap = devm_regmap_init_mmio(&pdev->dev, base, &apcs_regmap_config);
95 if (IS_ERR(regmap))
96 return PTR_ERR(regmap);
97
Sivaprakash Murugesan9b007932020-06-08 15:07:26 +053098 apcs_data = of_device_get_match_data(&pdev->dev);
Bjorn Andersson25bfee12017-05-27 16:14:04 -070099
Georgi Djakovc6a8b172017-12-05 17:46:56 +0200100 apcs->regmap = regmap;
Sivaprakash Murugesan9b007932020-06-08 15:07:26 +0530101 apcs->offset = apcs_data->offset;
Bjorn Andersson25bfee12017-05-27 16:14:04 -0700102
103 /* Initialize channel identifiers */
104 for (i = 0; i < ARRAY_SIZE(apcs->mbox_chans); i++)
105 apcs->mbox_chans[i].con_priv = (void *)i;
106
107 apcs->mbox.dev = &pdev->dev;
108 apcs->mbox.ops = &qcom_apcs_ipc_ops;
109 apcs->mbox.chans = apcs->mbox_chans;
110 apcs->mbox.num_chans = ARRAY_SIZE(apcs->mbox_chans);
111
Thierry Reding83dd44a2018-12-20 18:19:59 +0100112 ret = devm_mbox_controller_register(&pdev->dev, &apcs->mbox);
Bjorn Andersson25bfee12017-05-27 16:14:04 -0700113 if (ret) {
114 dev_err(&pdev->dev, "failed to register APCS IPC controller\n");
115 return ret;
116 }
117
Sivaprakash Murugesan9b007932020-06-08 15:07:26 +0530118 if (apcs_data->clk_name) {
Georgi Djakovc815d762017-12-05 17:46:57 +0200119 apcs->clk = platform_device_register_data(&pdev->dev,
Sivaprakash Murugesan9b007932020-06-08 15:07:26 +0530120 apcs_data->clk_name,
Shawn Guo96e39e92021-06-22 08:39:18 +0800121 PLATFORM_DEVID_AUTO,
Jorge Ramirez-Ortiz16d52f32019-08-29 10:27:59 +0200122 NULL, 0);
Georgi Djakovc815d762017-12-05 17:46:57 +0200123 if (IS_ERR(apcs->clk))
124 dev_err(&pdev->dev, "failed to register APCS clk\n");
125 }
126
Bjorn Andersson25bfee12017-05-27 16:14:04 -0700127 platform_set_drvdata(pdev, apcs);
128
129 return 0;
130}
131
132static int qcom_apcs_ipc_remove(struct platform_device *pdev)
133{
134 struct qcom_apcs_ipc *apcs = platform_get_drvdata(pdev);
Georgi Djakovc815d762017-12-05 17:46:57 +0200135 struct platform_device *clk = apcs->clk;
Bjorn Andersson25bfee12017-05-27 16:14:04 -0700136
Georgi Djakovc815d762017-12-05 17:46:57 +0200137 platform_device_unregister(clk);
Bjorn Andersson25bfee12017-05-27 16:14:04 -0700138
139 return 0;
140}
141
142/* .data is the offset of the ipc register within the global block */
143static const struct of_device_id qcom_apcs_ipc_of_match[] = {
Sivaprakash Murugesane9f901d2020-06-08 15:07:27 +0530144 { .compatible = "qcom,ipq6018-apcs-apps-global", .data = &ipq6018_apcs_data },
Shawn Guo4523ec82021-09-14 09:40:48 +0800145 { .compatible = "qcom,ipq8074-apcs-apps-global", .data = &msm8994_apcs_data },
Sivaprakash Murugesan9b007932020-06-08 15:07:26 +0530146 { .compatible = "qcom,msm8916-apcs-kpss-global", .data = &msm8916_apcs_data },
Shawn Guo8a7cdb12021-06-22 08:39:19 +0800147 { .compatible = "qcom,msm8939-apcs-kpss-global", .data = &msm8916_apcs_data },
Vladimir Lypake5c11ee2021-08-10 16:44:33 +0000148 { .compatible = "qcom,msm8953-apcs-kpss-global", .data = &msm8994_apcs_data },
Konrad Dybciodde68052020-06-24 17:01:03 +0200149 { .compatible = "qcom,msm8994-apcs-kpss-global", .data = &msm8994_apcs_data },
Sivaprakash Murugesan9b007932020-06-08 15:07:26 +0530150 { .compatible = "qcom,msm8996-apcs-hmss-global", .data = &msm8996_apcs_data },
Shawn Guo4523ec82021-09-14 09:40:48 +0800151 { .compatible = "qcom,msm8998-apcs-hmss-global", .data = &msm8994_apcs_data },
Shawn Guodb28a592021-09-14 09:40:50 +0800152 { .compatible = "qcom,qcm2290-apcs-hmss-global", .data = &msm8994_apcs_data },
Sivaprakash Murugesan9b007932020-06-08 15:07:26 +0530153 { .compatible = "qcom,qcs404-apcs-apps-global", .data = &msm8916_apcs_data },
154 { .compatible = "qcom,sc7180-apss-shared", .data = &apps_shared_apcs_data },
Bjorn Anderssond10c8512021-01-20 17:41:30 -0800155 { .compatible = "qcom,sc8180x-apss-shared", .data = &apps_shared_apcs_data },
Shawn Guo4523ec82021-09-14 09:40:48 +0800156 { .compatible = "qcom,sdm660-apcs-hmss-global", .data = &msm8994_apcs_data },
Sivaprakash Murugesan9b007932020-06-08 15:07:26 +0530157 { .compatible = "qcom,sdm845-apss-shared", .data = &apps_shared_apcs_data },
Shawn Guo4523ec82021-09-14 09:40:48 +0800158 { .compatible = "qcom,sm6125-apcs-hmss-global", .data = &msm8994_apcs_data },
Sivaprakash Murugesan9b007932020-06-08 15:07:26 +0530159 { .compatible = "qcom,sm8150-apss-shared", .data = &apps_shared_apcs_data },
Shawn Guo4523ec82021-09-14 09:40:48 +0800160 { .compatible = "qcom,sm6115-apcs-hmss-global", .data = &msm8994_apcs_data },
Manivannan Sadhasivamc319f782021-01-18 09:41:53 +0530161 { .compatible = "qcom,sdx55-apcs-gcc", .data = &sdx55_apcs_data },
Bjorn Andersson25bfee12017-05-27 16:14:04 -0700162 {}
163};
164MODULE_DEVICE_TABLE(of, qcom_apcs_ipc_of_match);
165
166static struct platform_driver qcom_apcs_ipc_driver = {
167 .probe = qcom_apcs_ipc_probe,
168 .remove = qcom_apcs_ipc_remove,
169 .driver = {
170 .name = "qcom_apcs_ipc",
171 .of_match_table = qcom_apcs_ipc_of_match,
172 },
173};
174
175static int __init qcom_apcs_ipc_init(void)
176{
177 return platform_driver_register(&qcom_apcs_ipc_driver);
178}
179postcore_initcall(qcom_apcs_ipc_init);
180
181static void __exit qcom_apcs_ipc_exit(void)
182{
183 platform_driver_unregister(&qcom_apcs_ipc_driver);
184}
185module_exit(qcom_apcs_ipc_exit);
186
187MODULE_LICENSE("GPL v2");
188MODULE_DESCRIPTION("Qualcomm APCS IPC driver");