blob: 62c780666a71ce91b2bd498e4bd9185806993cc4 [file] [log] [blame]
developere5e687d2023-08-08 16:05:33 +08001// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (c) 2023 MediaTek Inc. All Rights Reserved.
4 *
5 * Author: Ren-Ting Wang <ren-ting.wang@mediatek.com>
6 */
7
developer6a0a7102023-09-18 18:03:07 +08008#include <linux/debugfs.h>
developere5e687d2023-08-08 16:05:33 +08009#include <linux/device.h>
developer6a0a7102023-09-18 18:03:07 +080010#include <linux/err.h>
11#include <linux/io.h>
developere5e687d2023-08-08 16:05:33 +080012#include <linux/module.h>
developer6a0a7102023-09-18 18:03:07 +080013#include <linux/of.h>
14#include <linux/of_address.h>
developere5e687d2023-08-08 16:05:33 +080015#include <linux/of_platform.h>
16#include <linux/platform_device.h>
17
18#include "ctrl.h"
19#include "firmware.h"
20#include "hpdma.h"
21#include "hwspinlock.h"
22#include "internal.h"
23#include "mbox.h"
24#include "mcu.h"
25#include "netsys.h"
26#include "net-event.h"
27#include "ser.h"
28#include "tdma.h"
29#include "trm-mcu.h"
30#include "trm.h"
31#include "tunnel.h"
32#include "wdt.h"
33
developer6a0a7102023-09-18 18:03:07 +080034#define EFUSE_TOPS_POWER_OFF (0xD08)
35
developere5e687d2023-08-08 16:05:33 +080036struct device *tops_dev;
developerfbdb5112023-08-21 15:12:14 +080037struct dentry *tops_debugfs_root;
developere5e687d2023-08-08 16:05:33 +080038
39static int mtk_tops_post_init(struct platform_device *pdev)
40{
41 int ret = 0;
42
43 /* kick core */
44 ret = mtk_tops_mcu_bring_up(pdev);
45 if (ret) {
46 TOPS_ERR("mcu post init failed: %d\n", ret);
47 return ret;
48 }
49
50 /* offload tunnel protocol initialization */
51 ret = mtk_tops_tnl_offload_proto_setup(pdev);
52 if (ret) {
53 TOPS_ERR("tnl offload protocol init failed: %d\n", ret);
54 goto err_mcu_tear_down;
55 }
56
57 ret = mtk_tops_netevent_register(pdev);
58 if (ret) {
59 TOPS_ERR("netevent register fail: %d\n", ret);
60 goto err_offload_proto_tear_down;
61 }
62
63 /* create sysfs file */
64 ret = mtk_tops_ctrl_init(pdev);
65 if (ret) {
66 TOPS_ERR("ctrl init failed: %d\n", ret);
67 goto err_netevent_unregister;
68 }
69
70 ret = mtk_tops_ser_init(pdev);
71 if (ret) {
72 TOPS_ERR("ser init failed: %d\n", ret);
73 goto err_ctrl_deinit;
74 }
75
76 ret = mtk_tops_wdt_init(pdev);
77 if (ret) {
78 TOPS_ERR("wdt init failed: %d\n", ret);
79 goto err_ser_deinit;
80 }
81
82 return ret;
83
84err_ser_deinit:
85 mtk_tops_ser_deinit(pdev);
86
87err_ctrl_deinit:
88 mtk_tops_ctrl_deinit(pdev);
89
90err_netevent_unregister:
91 mtk_tops_netevent_unregister(pdev);
92
93err_offload_proto_tear_down:
94 mtk_tops_tnl_offload_proto_teardown(pdev);
95
96err_mcu_tear_down:
97 mtk_tops_mcu_tear_down(pdev);
98
99 return ret;
100}
101
102static int mtk_tops_probe(struct platform_device *pdev)
103{
104 int ret = 0;
105
106 tops_dev = &pdev->dev;
107
108 ret = mtk_tops_hwspinlock_init(pdev);
109 if (ret) {
110 TOPS_ERR("hwspinlock init failed: %d\n", ret);
111 return ret;
112 }
113
114 ret = mtk_tops_fw_init(pdev);
115 if (ret) {
116 TOPS_ERR("firmware init failed: %d\n", ret);
117 return ret;
118 }
119
120 ret = mtk_tops_mcu_init(pdev);
121 if (ret) {
122 TOPS_ERR("mcu init failed: %d\n", ret);
123 return ret;
124 }
125
126 ret = mtk_tops_netsys_init(pdev);
127 if (ret) {
128 TOPS_ERR("netsys init failed: %d\n", ret);
129 goto err_mcu_deinit;
130 }
131
132 ret = mtk_tops_tdma_init(pdev);
133 if (ret) {
134 TOPS_ERR("tdma init failed: %d\n", ret);
135 goto err_netsys_deinit;
136 }
137
138 ret = mtk_tops_tnl_offload_init(pdev);
139 if (ret) {
140 TOPS_ERR("tunnel table init failed: %d\n", ret);
141 goto err_tdma_deinit;
142 }
143
144 ret = mtk_tops_post_init(pdev);
145 if (ret)
146 goto err_tnl_offload_deinit;
147
148 TOPS_ERR("init done\n");
149 return ret;
150
151err_tnl_offload_deinit:
152 mtk_tops_tnl_offload_deinit(pdev);
153
154err_tdma_deinit:
155 mtk_tops_tdma_deinit(pdev);
156
157err_netsys_deinit:
158 mtk_tops_netsys_deinit(pdev);
159
160err_mcu_deinit:
161 mtk_tops_mcu_deinit(pdev);
162
163 return ret;
164}
165
166static int mtk_tops_remove(struct platform_device *pdev)
167{
168 mtk_tops_wdt_deinit(pdev);
169
170 mtk_tops_ser_deinit(pdev);
171
172 mtk_tops_ctrl_deinit(pdev);
173
174 mtk_tops_netevent_unregister(pdev);
175
176 mtk_tops_tnl_offload_proto_teardown(pdev);
177
178 mtk_tops_mcu_tear_down(pdev);
179
180 mtk_tops_tnl_offload_deinit(pdev);
181
182 mtk_tops_tdma_deinit(pdev);
183
184 mtk_tops_netsys_deinit(pdev);
185
186 mtk_tops_mcu_deinit(pdev);
187
188 return 0;
189}
190
191static const struct of_device_id tops_match[] = {
192 { .compatible = "mediatek,tops", },
193 { },
194};
195MODULE_DEVICE_TABLE(of, tops_match);
196
197static struct platform_driver mtk_tops_driver = {
198 .probe = mtk_tops_probe,
199 .remove = mtk_tops_remove,
200 .driver = {
201 .name = "mediatek,tops",
202 .owner = THIS_MODULE,
203 .of_match_table = tops_match,
204 },
205};
206
developer6a0a7102023-09-18 18:03:07 +0800207static int __init mtk_tops_hw_disabled(void)
208{
209 struct platform_device *efuse_pdev;
210 struct device_node *efuse_node;
211 struct resource res;
212 void __iomem *efuse_base;
213 int ret = 0;
214
215 efuse_node = of_find_compatible_node(NULL, NULL, "mediatek,efuse");
216 if (!efuse_node)
217 return -ENODEV;
218
219 efuse_pdev = of_find_device_by_node(efuse_node);
220 if (!efuse_pdev) {
221 ret = -ENODEV;
222 goto out;
223 }
224
225 if (of_address_to_resource(efuse_node, 0, &res)) {
226 ret = -ENXIO;
227 goto out;
228 }
229
230 /* since we are not probed yet, we cannot use devm_* API */
231 efuse_base = ioremap(res.start, resource_size(&res));
232 if (!efuse_base) {
233 ret = -ENOMEM;
234 goto out;
235 }
236
237 if (readl(efuse_base + EFUSE_TOPS_POWER_OFF))
238 ret = -ENODEV;
239
240 iounmap(efuse_base);
241
242out:
243 of_node_put(efuse_node);
244
245 return ret;
246}
247
developere5e687d2023-08-08 16:05:33 +0800248static int __init mtk_tops_init(void)
249{
developer6a0a7102023-09-18 18:03:07 +0800250 if (mtk_tops_hw_disabled())
251 return -ENODEV;
252
developerfbdb5112023-08-21 15:12:14 +0800253 tops_debugfs_root = debugfs_create_dir("tops", NULL);
254 if (IS_ERR(tops_debugfs_root)) {
255 TOPS_ERR("create tops debugfs root directory failed\n");
256 return PTR_ERR(tops_debugfs_root);
257 }
258
developere5e687d2023-08-08 16:05:33 +0800259 mtk_tops_mbox_init();
260
261 mtk_tops_hpdma_init();
262
263 mtk_tops_trm_init();
264
265 return platform_driver_register(&mtk_tops_driver);
266}
267
268static void __exit mtk_tops_exit(void)
269{
270 platform_driver_unregister(&mtk_tops_driver);
271
272 mtk_tops_trm_exit();
273
274 mtk_tops_hpdma_exit();
275
276 mtk_tops_mbox_exit();
developerfbdb5112023-08-21 15:12:14 +0800277
278 debugfs_remove_recursive(tops_debugfs_root);
developere5e687d2023-08-08 16:05:33 +0800279}
280
281module_init(mtk_tops_init);
282module_exit(mtk_tops_exit);
283
284MODULE_LICENSE("GPL v2");
285MODULE_DESCRIPTION("MediaTek TOPS Driver");
286MODULE_AUTHOR("Ren-Ting Wang <ren-ting.wang@mediatek.com>");