blob: 9667097573f6ec2efca110f542c9cb953e8e807d [file] [log] [blame]
developerfd40db22021-04-29 10:08:25 +08001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (c) 2018 MediaTek Inc.
4 */
5
6#include "mt753x.h"
7#include "mt753x_regs.h"
8
9struct mt753x_mapping mt753x_def_mapping[] = {
10 {
11 .name = "llllw",
12 .pvids = { 1, 1, 1, 1, 2, 2, 1 },
13 .members = { 0, 0x4f, 0x30 },
14 .etags = { 0, 0, 0 },
15 .vids = { 0, 1, 2 },
16 }, {
17 .name = "wllll",
18 .pvids = { 2, 1, 1, 1, 1, 2, 1 },
19 .members = { 0, 0x5e, 0x21 },
20 .etags = { 0, 0, 0 },
21 .vids = { 0, 1, 2 },
22 }, {
23 .name = "lwlll",
24 .pvids = { 1, 2, 1, 1, 1, 2, 1 },
25 .members = { 0, 0x5d, 0x22 },
26 .etags = { 0, 0, 0 },
27 .vids = { 0, 1, 2 },
developer1b76b3f2021-12-22 19:53:19 +080028 }, {
29 .name = "lllll",
30 .pvids = { 1, 1, 1, 1, 1, 1, 1 },
31 .members = { 0, 0x7f },
32 .etags = { 0, 0 },
33 .vids = { 0, 1 },
developerfd40db22021-04-29 10:08:25 +080034 },
35};
36
37void mt753x_vlan_ctrl(struct gsw_mt753x *gsw, u32 cmd, u32 val)
38{
39 int i;
40
41 mt753x_reg_write(gsw, VTCR,
42 VTCR_BUSY | ((cmd << VTCR_FUNC_S) & VTCR_FUNC_M) |
43 (val & VTCR_VID_M));
44
45 for (i = 0; i < 300; i++) {
46 u32 val = mt753x_reg_read(gsw, VTCR);
47
48 if ((val & VTCR_BUSY) == 0)
49 break;
50
51 usleep_range(1000, 1100);
52 }
53
54 if (i == 300)
55 dev_info(gsw->dev, "vtcr timeout\n");
56}
57
58static void mt753x_write_vlan_entry(struct gsw_mt753x *gsw, int vlan, u16 vid,
59 u8 ports, u8 etags)
60{
61 int port;
62 u32 val;
63
64 /* vlan port membership */
65 if (ports)
66 mt753x_reg_write(gsw, VAWD1,
67 IVL_MAC | VTAG_EN | VENTRY_VALID |
68 ((ports << PORT_MEM_S) & PORT_MEM_M));
69 else
70 mt753x_reg_write(gsw, VAWD1, 0);
71
72 /* egress mode */
73 val = 0;
74 for (port = 0; port < MT753X_NUM_PORTS; port++) {
75 if (etags & BIT(port))
76 val |= ETAG_CTRL_TAG << PORT_ETAG_S(port);
77 else
78 val |= ETAG_CTRL_UNTAG << PORT_ETAG_S(port);
79 }
80 mt753x_reg_write(gsw, VAWD2, val);
81
82 /* write to vlan table */
83 mt753x_vlan_ctrl(gsw, VTCR_WRITE_VLAN_ENTRY, vid);
84}
85
86void mt753x_apply_vlan_config(struct gsw_mt753x *gsw)
87{
88 int i, j;
89 u8 tag_ports;
90 u8 untag_ports;
91
92 /* set all ports as security mode */
93 for (i = 0; i < MT753X_NUM_PORTS; i++)
94 mt753x_reg_write(gsw, PCR(i),
95 PORT_MATRIX_M | SECURITY_MODE);
96
97 /* check if a port is used in tag/untag vlan egress mode */
98 tag_ports = 0;
99 untag_ports = 0;
100
101 for (i = 0; i < MT753X_NUM_VLANS; i++) {
102 u8 member = gsw->vlan_entries[i].member;
103 u8 etags = gsw->vlan_entries[i].etags;
104
105 if (!member)
106 continue;
107
108 for (j = 0; j < MT753X_NUM_PORTS; j++) {
109 if (!(member & BIT(j)))
110 continue;
111
112 if (etags & BIT(j))
113 tag_ports |= 1u << j;
114 else
115 untag_ports |= 1u << j;
116 }
117 }
118
119 /* set all untag-only ports as transparent and the rest as user port */
120 for (i = 0; i < MT753X_NUM_PORTS; i++) {
121 u32 pvc_mode = 0x8100 << STAG_VPID_S;
122
123 if (untag_ports & BIT(i) && !(tag_ports & BIT(i)))
124 pvc_mode = (0x8100 << STAG_VPID_S) |
125 (VA_TRANSPARENT_PORT << VLAN_ATTR_S);
126
127 if ((gsw->port5_cfg.stag_on && i == 5) ||
128 (gsw->port6_cfg.stag_on && i == 6))
129 pvc_mode = (0x8100 << STAG_VPID_S) | PVC_PORT_STAG;
130
131 mt753x_reg_write(gsw, PVC(i), pvc_mode);
132 }
133
134 /* first clear the switch vlan table */
135 for (i = 0; i < MT753X_NUM_VLANS; i++)
136 mt753x_write_vlan_entry(gsw, i, i, 0, 0);
137
138 /* now program only vlans with members to avoid
139 * clobbering remapped entries in later iterations
140 */
141 for (i = 0; i < MT753X_NUM_VLANS; i++) {
142 u16 vid = gsw->vlan_entries[i].vid;
143 u8 member = gsw->vlan_entries[i].member;
144 u8 etags = gsw->vlan_entries[i].etags;
145
146 if (member)
147 mt753x_write_vlan_entry(gsw, i, vid, member, etags);
148 }
149
150 /* Port Default PVID */
151 for (i = 0; i < MT753X_NUM_PORTS; i++) {
152 int vlan = gsw->port_entries[i].pvid;
153 u16 pvid = 0;
154 u32 val;
155
156 if (vlan < MT753X_NUM_VLANS && gsw->vlan_entries[vlan].member)
157 pvid = gsw->vlan_entries[vlan].vid;
158
159 val = mt753x_reg_read(gsw, PPBV1(i));
160 val &= ~GRP_PORT_VID_M;
161 val |= pvid;
162 mt753x_reg_write(gsw, PPBV1(i), val);
163 }
164}
165
166struct mt753x_mapping *mt753x_find_mapping(struct device_node *np)
167{
168 const char *map;
169 int i;
170
171 if (of_property_read_string(np, "mediatek,portmap", &map))
172 return NULL;
173
174 for (i = 0; i < ARRAY_SIZE(mt753x_def_mapping); i++)
175 if (!strcmp(map, mt753x_def_mapping[i].name))
176 return &mt753x_def_mapping[i];
177
178 return NULL;
179}
180
181void mt753x_apply_mapping(struct gsw_mt753x *gsw, struct mt753x_mapping *map)
182{
183 int i = 0;
184
185 for (i = 0; i < MT753X_NUM_PORTS; i++)
186 gsw->port_entries[i].pvid = map->pvids[i];
187
188 for (i = 0; i < MT753X_NUM_VLANS; i++) {
189 gsw->vlan_entries[i].member = map->members[i];
190 gsw->vlan_entries[i].etags = map->etags[i];
191 gsw->vlan_entries[i].vid = map->vids[i];
192 }
193}