blob: e1770c9fbda19be7c42a63ad7eb1a11182147386 [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
8#include <linux/device.h>
9#include <linux/io.h>
10#include <linux/mutex.h>
11#include <linux/of.h>
12#include <linux/of_address.h>
13#include <linux/platform_device.h>
14
15#include <mtk_hnat/hnat.h>
16
17#include <pce/netsys.h>
18
developer0fb30d52023-12-04 09:51:36 +080019#include "tops/hpdma.h"
20#include "tops/internal.h"
21#include "tops/mcu.h"
22#include "tops/netsys.h"
23#include "tops/tdma.h"
24#include "tops/trm.h"
developere5e687d2023-08-08 16:05:33 +080025
26/* Netsys dump length */
27#define FE_BASE_LEN (0x2900)
28
29#define PPE_DEFAULT_ENTRY_SIZE (0x400)
30
31static int netsys_trm_hw_dump(void *dst, u32 ofs, u32 len);
32
33struct netsys_hw {
34 void __iomem *base;
developerd80acd02024-02-20 14:28:44 +080035 u32 ppe_num;
developere5e687d2023-08-08 16:05:33 +080036};
37
38static struct netsys_hw netsys;
39
40static struct trm_config netsys_trm_configs[] = {
41 {
42 TRM_CFG_EN("netsys-fe",
43 FE_BASE, FE_BASE_LEN,
44 0x0, FE_BASE_LEN,
45 0)
46 },
47};
48
49static struct trm_hw_config netsys_trm_hw_cfg = {
50 .trm_cfgs = netsys_trm_configs,
51 .cfg_len = ARRAY_SIZE(netsys_trm_configs),
52 .trm_hw_dump = netsys_trm_hw_dump,
53};
54
55static inline void netsys_write(u32 reg, u32 val)
56{
57 writel(val, netsys.base + reg);
58}
59
60static inline void netsys_set(u32 reg, u32 mask)
61{
62 setbits(netsys.base + reg, mask);
63}
64
65static inline void netsys_clr(u32 reg, u32 mask)
66{
67 clrbits(netsys.base + reg, mask);
68}
69
70static inline void netsys_rmw(u32 reg, u32 mask, u32 val)
71{
72 clrsetbits(netsys.base + reg, mask, val);
73}
74
75static inline u32 netsys_read(u32 reg)
76{
77 return readl(netsys.base + reg);
78}
79
80static int netsys_trm_hw_dump(void *dst, u32 start_addr, u32 len)
81{
82 u32 ofs;
83
84 if (unlikely(!dst))
85 return -ENODEV;
86
87 for (ofs = 0; len > 0; len -= 0x4, ofs += 0x4)
88 writel(netsys_read(start_addr + ofs), dst + ofs);
89
90 return 0;
91}
92
93static inline void ppe_rmw(enum pse_port ppe, u32 reg, u32 mask, u32 val)
94{
95 if (ppe == PSE_PORT_PPE0)
96 netsys_rmw(PPE0_BASE + reg, mask, val);
97 else if (ppe == PSE_PORT_PPE1)
98 netsys_rmw(PPE1_BASE + reg, mask, val);
99 else if (ppe == PSE_PORT_PPE2)
100 netsys_rmw(PPE2_BASE + reg, mask, val);
101}
102
103static inline u32 ppe_read(enum pse_port ppe, u32 reg)
104{
105 if (ppe == PSE_PORT_PPE0)
106 return netsys_read(PPE0_BASE + reg);
107 else if (ppe == PSE_PORT_PPE1)
108 return netsys_read(PPE1_BASE + reg);
109 else if (ppe == PSE_PORT_PPE2)
110 return netsys_read(PPE2_BASE + reg);
111
112 return 0;
113}
114
developerd80acd02024-02-20 14:28:44 +0800115u32 mtk_tops_netsys_ppe_get_num(void)
116{
117 return netsys.ppe_num;
118}
119
developere5e687d2023-08-08 16:05:33 +0800120u32 mtk_tops_netsys_ppe_get_max_entry_num(u32 ppe_id)
121{
122 u32 tbl_entry_num;
123 enum pse_port ppe;
124
125 if (ppe_id == 0)
126 ppe = PSE_PORT_PPE0;
127 else if (ppe_id == 1)
128 ppe = PSE_PORT_PPE1;
129 else if (ppe_id == 2)
130 ppe = PSE_PORT_PPE2;
131 else
132 return PPE_DEFAULT_ENTRY_SIZE << 5; /* max entry count */
133
134 tbl_entry_num = ppe_read(ppe, PPE_TBL_CFG);
135 if (tbl_entry_num > 5)
136 return PPE_DEFAULT_ENTRY_SIZE << 5;
137
138 return PPE_DEFAULT_ENTRY_SIZE << tbl_entry_num;
139}
140
developerd80acd02024-02-20 14:28:44 +0800141static int mtk_tops_netsys_base_init(struct platform_device *pdev)
developere5e687d2023-08-08 16:05:33 +0800142{
143 struct device_node *fe_mem = NULL;
144 struct resource res;
145 int ret = 0;
146
147 fe_mem = of_parse_phandle(pdev->dev.of_node, "fe_mem", 0);
148 if (!fe_mem) {
149 TOPS_ERR("can not find fe_mem node\n");
150 return -ENODEV;
151 }
152
developerd80acd02024-02-20 14:28:44 +0800153 if (of_address_to_resource(fe_mem, 0, &res)) {
154 ret = -ENXIO;
155 goto out;
156 }
developere5e687d2023-08-08 16:05:33 +0800157
158 netsys.base = devm_ioremap(&pdev->dev, res.start, resource_size(&res));
developerd80acd02024-02-20 14:28:44 +0800159 if (!netsys.base) {
160 ret = -ENOMEM;
161 goto out;
162 }
163
164out:
165 of_node_put(fe_mem);
166
167 return ret;
168}
169
170static int mtk_tops_netsys_ppe_num_init(struct platform_device *pdev)
171{
172 struct device_node *hnat = NULL;
173 u32 val = 0;
174 int ret = 0;
175
176 hnat = of_parse_phandle(pdev->dev.of_node, "hnat", 0);
177 if (!hnat) {
178 TOPS_ERR("can not find hnat node\n");
179 return -ENODEV;
180 }
181
182 ret = of_property_read_u32(hnat, "mtketh-ppe-num", &val);
183 if (ret)
184 netsys.ppe_num = 1;
185 else
186 netsys.ppe_num = val;
187
188 of_node_put(hnat);
189
190 return 0;
191}
192
193int mtk_tops_netsys_init(struct platform_device *pdev)
194{
195 int ret;
196
197 ret = mtk_tops_netsys_base_init(pdev);
198 if (ret)
199 return ret;
200
201 ret = mtk_tops_netsys_ppe_num_init(pdev);
202 if (ret)
203 return ret;
developere5e687d2023-08-08 16:05:33 +0800204
205 ret = mtk_trm_hw_config_register(TRM_NETSYS, &netsys_trm_hw_cfg);
206 if (ret)
207 return ret;
208
209 return ret;
210}
211
212void mtk_tops_netsys_deinit(struct platform_device *pdev)
213{
214 mtk_trm_hw_config_unregister(TRM_NETSYS, &netsys_trm_hw_cfg);
215}