blob: 7deb502e73d9064ed20936ece4d359c5a9f3ab45 [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
19#include "hpdma.h"
20#include "internal.h"
21#include "mcu.h"
22#include "netsys.h"
23#include "tdma.h"
24#include "trm.h"
25
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;
35};
36
37static struct netsys_hw netsys;
38
39static struct trm_config netsys_trm_configs[] = {
40 {
41 TRM_CFG_EN("netsys-fe",
42 FE_BASE, FE_BASE_LEN,
43 0x0, FE_BASE_LEN,
44 0)
45 },
46};
47
48static struct trm_hw_config netsys_trm_hw_cfg = {
49 .trm_cfgs = netsys_trm_configs,
50 .cfg_len = ARRAY_SIZE(netsys_trm_configs),
51 .trm_hw_dump = netsys_trm_hw_dump,
52};
53
54static inline void netsys_write(u32 reg, u32 val)
55{
56 writel(val, netsys.base + reg);
57}
58
59static inline void netsys_set(u32 reg, u32 mask)
60{
61 setbits(netsys.base + reg, mask);
62}
63
64static inline void netsys_clr(u32 reg, u32 mask)
65{
66 clrbits(netsys.base + reg, mask);
67}
68
69static inline void netsys_rmw(u32 reg, u32 mask, u32 val)
70{
71 clrsetbits(netsys.base + reg, mask, val);
72}
73
74static inline u32 netsys_read(u32 reg)
75{
76 return readl(netsys.base + reg);
77}
78
79static int netsys_trm_hw_dump(void *dst, u32 start_addr, u32 len)
80{
81 u32 ofs;
82
83 if (unlikely(!dst))
84 return -ENODEV;
85
86 for (ofs = 0; len > 0; len -= 0x4, ofs += 0x4)
87 writel(netsys_read(start_addr + ofs), dst + ofs);
88
89 return 0;
90}
91
92static inline void ppe_rmw(enum pse_port ppe, u32 reg, u32 mask, u32 val)
93{
94 if (ppe == PSE_PORT_PPE0)
95 netsys_rmw(PPE0_BASE + reg, mask, val);
96 else if (ppe == PSE_PORT_PPE1)
97 netsys_rmw(PPE1_BASE + reg, mask, val);
98 else if (ppe == PSE_PORT_PPE2)
99 netsys_rmw(PPE2_BASE + reg, mask, val);
100}
101
102static inline u32 ppe_read(enum pse_port ppe, u32 reg)
103{
104 if (ppe == PSE_PORT_PPE0)
105 return netsys_read(PPE0_BASE + reg);
106 else if (ppe == PSE_PORT_PPE1)
107 return netsys_read(PPE1_BASE + reg);
108 else if (ppe == PSE_PORT_PPE2)
109 return netsys_read(PPE2_BASE + reg);
110
111 return 0;
112}
113
114u32 mtk_tops_netsys_ppe_get_max_entry_num(u32 ppe_id)
115{
116 u32 tbl_entry_num;
117 enum pse_port ppe;
118
119 if (ppe_id == 0)
120 ppe = PSE_PORT_PPE0;
121 else if (ppe_id == 1)
122 ppe = PSE_PORT_PPE1;
123 else if (ppe_id == 2)
124 ppe = PSE_PORT_PPE2;
125 else
126 return PPE_DEFAULT_ENTRY_SIZE << 5; /* max entry count */
127
128 tbl_entry_num = ppe_read(ppe, PPE_TBL_CFG);
129 if (tbl_entry_num > 5)
130 return PPE_DEFAULT_ENTRY_SIZE << 5;
131
132 return PPE_DEFAULT_ENTRY_SIZE << tbl_entry_num;
133}
134
135int mtk_tops_netsys_init(struct platform_device *pdev)
136{
137 struct device_node *fe_mem = NULL;
138 struct resource res;
139 int ret = 0;
140
141 fe_mem = of_parse_phandle(pdev->dev.of_node, "fe_mem", 0);
142 if (!fe_mem) {
143 TOPS_ERR("can not find fe_mem node\n");
144 return -ENODEV;
145 }
146
147 if (of_address_to_resource(fe_mem, 0, &res))
148 return -ENXIO;
149
150 netsys.base = devm_ioremap(&pdev->dev, res.start, resource_size(&res));
151 if (!netsys.base)
152 return -ENOMEM;
153
154 ret = mtk_trm_hw_config_register(TRM_NETSYS, &netsys_trm_hw_cfg);
155 if (ret)
156 return ret;
157
158 return ret;
159}
160
161void mtk_tops_netsys_deinit(struct platform_device *pdev)
162{
163 mtk_trm_hw_config_unregister(TRM_NETSYS, &netsys_trm_hw_cfg);
164}