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