ramips: backport mt7530/762x switch fixes
[openwrt/staging/chunkeey.git] / target / linux / ramips / patches-4.4 / 0519-gsw_mt7621.patch
1 --- a/drivers/net/ethernet/mediatek/mt7530.c
2 +++ b/drivers/net/ethernet/mediatek/mt7530.c
3 @@ -44,6 +44,12 @@
4 #define MT7530_MAX_VID 4095
5 #define MT7530_MIN_VID 0
6
7 +#define MT7530_PORT_MIB_TXB_ID 2 /* TxGOC */
8 +#define MT7530_PORT_MIB_RXB_ID 6 /* RxGOC */
9 +
10 +#define MT7621_PORT_MIB_TXB_ID 18 /* TxByte */
11 +#define MT7621_PORT_MIB_RXB_ID 37 /* RxByte */
12 +
13 /* registers */
14 #define REG_ESW_VLAN_VTCR 0x90
15 #define REG_ESW_VLAN_VAWD1 0x94
16 @@ -214,6 +220,12 @@ struct mt7530_mapping {
17 .members = { 0, 0x7e, 0x41 },
18 .etags = { 0, 0x40, 0x40 },
19 .vids = { 0, 1, 2 },
20 + }, {
21 + .name = "lwlll",
22 + .pvids = { 1, 2, 1, 1, 1, 1, 1 },
23 + .members = { 0, 0x7d, 0x42 },
24 + .etags = { 0, 0x40, 0x40 },
25 + .vids = { 0, 1, 2 },
26 },
27 };
28
29 @@ -467,6 +479,14 @@ mt7530_set_vid(struct switch_dev *dev, c
30 }
31
32 static int
33 +mt7621_get_vid(struct switch_dev *dev, const struct switch_attr *attr,
34 + struct switch_val *val)
35 +{
36 + val->value.i = val->port_vlan;
37 + return 0;
38 +}
39 +
40 +static int
41 mt7530_get_vid(struct switch_dev *dev, const struct switch_attr *attr,
42 struct switch_val *val)
43 {
44 @@ -485,6 +505,52 @@ mt7530_get_vid(struct switch_dev *dev, c
45 return 0;
46 }
47
48 +static void
49 +mt7530_write_vlan_entry(struct mt7530_priv *priv, int vlan, u16 vid,
50 + u8 ports, u8 etags)
51 +{
52 + int port;
53 + u32 val;
54 +
55 +#ifndef CONFIG_SOC_MT7621
56 + /* vid of vlan */
57 + val = mt7530_r32(priv, REG_ESW_VLAN_VTIM(vlan));
58 + if (vlan % 2 == 0) {
59 + val &= 0xfff000;
60 + val |= vid;
61 + } else {
62 + val &= 0xfff;
63 + val |= (vid << 12);
64 + }
65 + mt7530_w32(priv, REG_ESW_VLAN_VTIM(vlan), val);
66 +#endif
67 +
68 + /* vlan port membership */
69 + if (ports)
70 + mt7530_w32(priv, REG_ESW_VLAN_VAWD1, REG_ESW_VLAN_VAWD1_IVL_MAC |
71 + REG_ESW_VLAN_VAWD1_VTAG_EN | (ports << 16) |
72 + REG_ESW_VLAN_VAWD1_VALID);
73 + else
74 + mt7530_w32(priv, REG_ESW_VLAN_VAWD1, 0);
75 +
76 + /* egress mode */
77 + val = 0;
78 + for (port = 0; port < MT7530_NUM_PORTS; port++) {
79 + if (etags & BIT(port))
80 + val |= ETAG_CTRL_TAG << (port * 2);
81 + else
82 + val |= ETAG_CTRL_UNTAG << (port * 2);
83 + }
84 + mt7530_w32(priv, REG_ESW_VLAN_VAWD2, val);
85 +
86 + /* write to vlan table */
87 +#ifdef CONFIG_SOC_MT7621
88 + mt7530_vtcr(priv, 1, vid);
89 +#else
90 + mt7530_vtcr(priv, 1, vlan);
91 +#endif
92 +}
93 +
94 static int
95 mt7530_apply_config(struct switch_dev *dev)
96 {
97 @@ -541,51 +607,33 @@ mt7530_apply_config(struct switch_dev *d
98 mt7530_w32(priv, REG_ESW_PORT_PVC(i), pvc_mode);
99 }
100
101 + /* first clear the swtich vlan table */
102 + for (i = 0; i < MT7530_NUM_VLANS; i++)
103 + mt7530_write_vlan_entry(priv, i, i, 0, 0);
104 +
105 + /* now program only vlans with members to avoid
106 + clobbering remapped entries in later iterations */
107 for (i = 0; i < MT7530_NUM_VLANS; i++) {
108 u16 vid = priv->vlan_entries[i].vid;
109 u8 member = priv->vlan_entries[i].member;
110 u8 etags = priv->vlan_entries[i].etags;
111 - u32 val;
112
113 - /* vid of vlan */
114 - val = mt7530_r32(priv, REG_ESW_VLAN_VTIM(i));
115 - if (i % 2 == 0) {
116 - val &= 0xfff000;
117 - val |= vid;
118 - } else {
119 - val &= 0xfff;
120 - val |= (vid << 12);
121 - }
122 - mt7530_w32(priv, REG_ESW_VLAN_VTIM(i), val);
123 -
124 - /* vlan port membership */
125 if (member)
126 - mt7530_w32(priv, REG_ESW_VLAN_VAWD1, REG_ESW_VLAN_VAWD1_IVL_MAC |
127 - REG_ESW_VLAN_VAWD1_VTAG_EN | (member << 16) |
128 - REG_ESW_VLAN_VAWD1_VALID);
129 - else
130 - mt7530_w32(priv, REG_ESW_VLAN_VAWD1, 0);
131 -
132 - /* egress mode */
133 - val = 0;
134 - for (j = 0; j < MT7530_NUM_PORTS; j++) {
135 - if (etags & BIT(j))
136 - val |= ETAG_CTRL_TAG << (j * 2);
137 - else
138 - val |= ETAG_CTRL_UNTAG << (j * 2);
139 - }
140 - mt7530_w32(priv, REG_ESW_VLAN_VAWD2, val);
141 -
142 - /* write to vlan table */
143 - mt7530_vtcr(priv, 1, i);
144 + mt7530_write_vlan_entry(priv, i, vid, member, etags);
145 }
146
147 /* Port Default PVID */
148 for (i = 0; i < MT7530_NUM_PORTS; i++) {
149 + int vlan = priv->port_entries[i].pvid;
150 + u16 pvid = 0;
151 u32 val;
152 +
153 + if (vlan < MT7530_NUM_VLANS && priv->vlan_entries[vlan].member)
154 + pvid = priv->vlan_entries[vlan].vid;
155 +
156 val = mt7530_r32(priv, REG_ESW_PORT_PPBV1(i));
157 val &= ~0xfff;
158 - val |= priv->port_entries[i].pvid;
159 + val |= pvid;
160 mt7530_w32(priv, REG_ESW_PORT_PPBV1(i), val);
161 }
162
163 @@ -739,6 +787,34 @@ static int mt7530_sw_get_port_mib(struct
164 return 0;
165 }
166
167 +static int mt7530_get_port_stats(struct switch_dev *dev, int port,
168 + struct switch_port_stats *stats)
169 +{
170 + struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev);
171 +
172 + if (port < 0 || port >= MT7530_NUM_PORTS)
173 + return -EINVAL;
174 +
175 + stats->tx_bytes = get_mib_counter_port_7620(priv, MT7530_PORT_MIB_TXB_ID, port);
176 + stats->rx_bytes = get_mib_counter_port_7620(priv, MT7530_PORT_MIB_RXB_ID, port);
177 +
178 + return 0;
179 +}
180 +
181 +static int mt7621_get_port_stats(struct switch_dev *dev, int port,
182 + struct switch_port_stats *stats)
183 +{
184 + struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev);
185 +
186 + if (port < 0 || port >= MT7530_NUM_PORTS)
187 + return -EINVAL;
188 +
189 + stats->tx_bytes = get_mib_counter(priv, MT7621_PORT_MIB_TXB_ID, port);
190 + stats->rx_bytes = get_mib_counter(priv, MT7621_PORT_MIB_RXB_ID, port);
191 +
192 + return 0;
193 +}
194 +
195 static const struct switch_attr mt7530_global[] = {
196 {
197 .type = SWITCH_TYPE_INT,
198 @@ -767,6 +843,17 @@ static const struct switch_attr mt7621_p
199 },
200 };
201
202 +static const struct switch_attr mt7621_vlan[] = {
203 + {
204 + .type = SWITCH_TYPE_INT,
205 + .name = "vid",
206 + .description = "VLAN ID (0-4094)",
207 + .set = mt7530_set_vid,
208 + .get = mt7621_get_vid,
209 + .max = 4094,
210 + },
211 +};
212 +
213 static const struct switch_attr mt7530_port[] = {
214 {
215 .type = SWITCH_TYPE_STRING,
216 @@ -798,14 +885,15 @@ static const struct switch_dev_ops mt762
217 .n_attr = ARRAY_SIZE(mt7621_port),
218 },
219 .attr_vlan = {
220 - .attr = mt7530_vlan,
221 - .n_attr = ARRAY_SIZE(mt7530_vlan),
222 + .attr = mt7621_vlan,
223 + .n_attr = ARRAY_SIZE(mt7621_vlan),
224 },
225 .get_vlan_ports = mt7530_get_vlan_ports,
226 .set_vlan_ports = mt7530_set_vlan_ports,
227 .get_port_pvid = mt7530_get_port_pvid,
228 .set_port_pvid = mt7530_set_port_pvid,
229 .get_port_link = mt7530_get_port_link,
230 + .get_port_stats = mt7621_get_port_stats,
231 .apply_config = mt7530_apply_config,
232 .reset_switch = mt7530_reset_switch,
233 };
234 @@ -828,6 +916,7 @@ static const struct switch_dev_ops mt753
235 .get_port_pvid = mt7530_get_port_pvid,
236 .set_port_pvid = mt7530_set_port_pvid,
237 .get_port_link = mt7530_get_port_link,
238 + .get_port_stats = mt7530_get_port_stats,
239 .apply_config = mt7530_apply_config,
240 .reset_switch = mt7530_reset_switch,
241 };
242 @@ -881,7 +970,7 @@ mt7530_probe(struct device *dev, void __
243
244 /* magic vodoo */
245 if (!IS_ENABLED(CONFIG_SOC_MT7621) && bus && mt7530_r32(mt7530, REG_HWTRAP) != 0x1117edf) {
246 - dev_info(dev, "fixing up MHWTRAP register - bootloader probably played with it\n");
247 + dev_info(dev, "fixing up MHWTRAP register - bootloader probably played with it\n");
248 mt7530_w32(mt7530, REG_HWTRAP, 0x1117edf);
249 }
250 dev_info(dev, "loaded %s driver\n", swdev->name);