blob: 0350be6641623ea13ca87f00f623744ec40537f0 [file] [log] [blame]
developer1966afb2023-08-08 16:02:18 +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/err.h>
10#include <linux/of.h>
11#include <linux/of_platform.h>
12
13#include "pce/internal.h"
14#include "pce/tport_map.h"
15
16int mtk_pce_tport_map_ts_config_read(enum ts_config_entry entry,
17 struct tsc_desc *ts_cfg)
18{
19 struct fe_mem_msg msg;
20 int ret = 0;
21
22 if (!ts_cfg)
23 return -EINVAL;
24
25 if (!(TS_CONFIG_MASK & BIT(entry))) {
26 PCE_ERR("invalid ts config entry: %u\n", entry);
27 return -EPERM;
28 }
29
30 mtk_pce_fe_mem_msg_config(&msg, FE_MEM_CMD_READ, FE_MEM_TYPE_TS_CONFIG, entry);
31 memset(&msg.raw, 0, sizeof(msg.raw));
32
33 ret = mtk_pce_fe_mem_msg_send(&msg);
34 if (ret) {
35 PCE_NOTICE("fe_mem send msg failed: %d\n", ret);
36 return ret;
37 }
38
39 memcpy(ts_cfg, &msg.tdesc, sizeof(*ts_cfg));
40
41 return ret;
42}
43
44int mtk_pce_tport_map_ts_config_write(enum ts_config_entry entry,
45 struct tsc_desc *ts_cfg)
46{
47 struct fe_mem_msg msg;
48 int ret = 0;
49
50 if (!ts_cfg)
51 return -EINVAL;
52
53 if (!(TS_CONFIG_MASK & BIT(entry))) {
54 PCE_NOTICE("invalid ts config entry: %u\n", entry);
55 return -EPERM;
56 }
57
58 mtk_pce_fe_mem_msg_config(&msg, FE_MEM_CMD_WRITE, FE_MEM_TYPE_TS_CONFIG, entry);
59 memset(&msg.raw, 0, sizeof(msg.raw));
60 memcpy(&msg.raw, ts_cfg, sizeof(struct tsc_desc));
61
62 ret = mtk_pce_fe_mem_msg_send(&msg);
63 if (ret) {
64 PCE_NOTICE("fe_mem send msg failed: %d\n", ret);
65 return ret;
66 }
67
68 return ret;
69}
70
71int mtk_pce_tport_map_ppe_read(enum pse_port ppe, u64 *map)
72{
73 if (!map)
74 return -EINVAL;
75
76 if (!(PSE_PORT_PPE_MASK & BIT(ppe))) {
77 PCE_NOTICE("invalid ppe index: %u\n", ppe);
78 return -EPERM;
79 }
80
81 *map = mtk_pce_ppe_read(ppe, PPE_TPORT_TBL_0);
82 *map |= ((u64)mtk_pce_ppe_read(ppe, PPE_TPORT_TBL_1)) << 32;
83
84 return 0;
85}
86
87static int mtk_pce_tport_map_update_ts_config(enum ts_config_entry entry,
88 u32 tport_idx,
89 enum pse_port target)
90{
91 struct tsc_desc ts_cfg;
92 int ret = 0;
93
94 ret = mtk_pce_tport_map_ts_config_read(entry, &ts_cfg);
95 if (ret)
96 return ret;
97
98 if (tport_idx < TPORT_IDX_MAX / 2) {
99 ts_cfg.tport_map_lower &= (~(0xF << (tport_idx * PSE_PER_PORT_BITS)));
100 ts_cfg.tport_map_lower |= (target << (tport_idx * PSE_PER_PORT_BITS));
101 } else {
102 ts_cfg.tport_map_upper &= (~(0xF << (tport_idx * PSE_PER_PORT_BITS)));
103 ts_cfg.tport_map_upper |= (target << (tport_idx * PSE_PER_PORT_BITS));
104 }
105
106 ret = mtk_pce_tport_map_ts_config_write(entry, &ts_cfg);
107 if (ret)
108 return ret;
109
110 return ret;
111}
112
113static int mtk_pce_tport_map_update_ppe(enum pse_port ppe,
114 u32 tport_idx,
115 enum pse_port target)
116{
117 u32 mask = (PSE_PER_PORT_MASK
118 << ((tport_idx % (TPORT_IDX_MAX / 2)) * PSE_PER_PORT_BITS));
119 u32 val = ((target & PSE_PER_PORT_MASK)
120 << ((tport_idx % (TPORT_IDX_MAX / 2)) * PSE_PER_PORT_BITS));
121
122 if (tport_idx < TPORT_IDX_MAX / 2)
123 mtk_pce_ppe_rmw(ppe, PPE_TPORT_TBL_0, mask, val);
124 else
125 mtk_pce_ppe_rmw(ppe, PPE_TPORT_TBL_1, mask, val);
126
127 return 0;
128}
129
130/*
131 * update tport idx mapping
132 * pse_port: the pse port idx that is going to be modified
133 * tport_idx: the tport idx that is going to be modified
134 * target: the next port for packet when the packet is at pse_port with tport_idx
135 */
136int mtk_pce_tport_map_pse_port_update(enum pse_port pse_port,
137 u32 tport_idx,
138 enum pse_port target)
139{
140 int ret = 0;
141
142 if (pse_port >= __PSE_PORT_MAX || target >= __PSE_PORT_MAX) {
143 PCE_NOTICE("invalid pse_port: %u, target: %u\n", pse_port, target);
144 return -EPERM;
145 }
146
147 if (tport_idx >= TPORT_IDX_MAX) {
148 PCE_NOTICE("invalid tport_idx: %u\n", tport_idx);
149 return -EPERM;
150 }
151
152 if (TS_CONFIG_MASK & BIT(pse_port))
153 ret = mtk_pce_tport_map_update_ts_config(pse_port, tport_idx, target);
154 else if (PSE_PORT_PPE_MASK & BIT(pse_port))
155 ret = mtk_pce_tport_map_update_ppe(pse_port, tport_idx, target);
156 else
157 ret = -EINVAL;
158
159 if (ret)
160 PCE_ERR("update tport map failed: %d\n", ret);
161
162 return ret;
163}