dt-bindings: mtd: ingenic: Use standard ecc-engine property
[linux/fpc-iii.git] / drivers / net / dsa / rtl8366.c
blob6dedd43442cc5775980725bbda8c3c7d5ee68443
1 // SPDX-License-Identifier: GPL-2.0
2 /* Realtek SMI library helpers for the RTL8366x variants
3 * RTL8366RB and RTL8366S
5 * Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org>
6 * Copyright (C) 2009-2010 Gabor Juhos <juhosg@openwrt.org>
7 * Copyright (C) 2010 Antti Seppälä <a.seppala@gmail.com>
8 * Copyright (C) 2010 Roman Yeryomin <roman@advem.lv>
9 * Copyright (C) 2011 Colin Leitner <colin.leitner@googlemail.com>
11 #include <linux/if_bridge.h>
12 #include <net/dsa.h>
14 #include "realtek-smi.h"
16 int rtl8366_mc_is_used(struct realtek_smi *smi, int mc_index, int *used)
18 int ret;
19 int i;
21 *used = 0;
22 for (i = 0; i < smi->num_ports; i++) {
23 int index = 0;
25 ret = smi->ops->get_mc_index(smi, i, &index);
26 if (ret)
27 return ret;
29 if (mc_index == index) {
30 *used = 1;
31 break;
35 return 0;
37 EXPORT_SYMBOL_GPL(rtl8366_mc_is_used);
39 int rtl8366_set_vlan(struct realtek_smi *smi, int vid, u32 member,
40 u32 untag, u32 fid)
42 struct rtl8366_vlan_4k vlan4k;
43 int ret;
44 int i;
46 /* Update the 4K table */
47 ret = smi->ops->get_vlan_4k(smi, vid, &vlan4k);
48 if (ret)
49 return ret;
51 vlan4k.member = member;
52 vlan4k.untag = untag;
53 vlan4k.fid = fid;
54 ret = smi->ops->set_vlan_4k(smi, &vlan4k);
55 if (ret)
56 return ret;
58 /* Try to find an existing MC entry for this VID */
59 for (i = 0; i < smi->num_vlan_mc; i++) {
60 struct rtl8366_vlan_mc vlanmc;
62 ret = smi->ops->get_vlan_mc(smi, i, &vlanmc);
63 if (ret)
64 return ret;
66 if (vid == vlanmc.vid) {
67 /* update the MC entry */
68 vlanmc.member = member;
69 vlanmc.untag = untag;
70 vlanmc.fid = fid;
72 ret = smi->ops->set_vlan_mc(smi, i, &vlanmc);
73 break;
77 return ret;
79 EXPORT_SYMBOL_GPL(rtl8366_set_vlan);
81 int rtl8366_get_pvid(struct realtek_smi *smi, int port, int *val)
83 struct rtl8366_vlan_mc vlanmc;
84 int ret;
85 int index;
87 ret = smi->ops->get_mc_index(smi, port, &index);
88 if (ret)
89 return ret;
91 ret = smi->ops->get_vlan_mc(smi, index, &vlanmc);
92 if (ret)
93 return ret;
95 *val = vlanmc.vid;
96 return 0;
98 EXPORT_SYMBOL_GPL(rtl8366_get_pvid);
100 int rtl8366_set_pvid(struct realtek_smi *smi, unsigned int port,
101 unsigned int vid)
103 struct rtl8366_vlan_mc vlanmc;
104 struct rtl8366_vlan_4k vlan4k;
105 int ret;
106 int i;
108 /* Try to find an existing MC entry for this VID */
109 for (i = 0; i < smi->num_vlan_mc; i++) {
110 ret = smi->ops->get_vlan_mc(smi, i, &vlanmc);
111 if (ret)
112 return ret;
114 if (vid == vlanmc.vid) {
115 ret = smi->ops->set_vlan_mc(smi, i, &vlanmc);
116 if (ret)
117 return ret;
119 ret = smi->ops->set_mc_index(smi, port, i);
120 return ret;
124 /* We have no MC entry for this VID, try to find an empty one */
125 for (i = 0; i < smi->num_vlan_mc; i++) {
126 ret = smi->ops->get_vlan_mc(smi, i, &vlanmc);
127 if (ret)
128 return ret;
130 if (vlanmc.vid == 0 && vlanmc.member == 0) {
131 /* Update the entry from the 4K table */
132 ret = smi->ops->get_vlan_4k(smi, vid, &vlan4k);
133 if (ret)
134 return ret;
136 vlanmc.vid = vid;
137 vlanmc.member = vlan4k.member;
138 vlanmc.untag = vlan4k.untag;
139 vlanmc.fid = vlan4k.fid;
140 ret = smi->ops->set_vlan_mc(smi, i, &vlanmc);
141 if (ret)
142 return ret;
144 ret = smi->ops->set_mc_index(smi, port, i);
145 return ret;
149 /* MC table is full, try to find an unused entry and replace it */
150 for (i = 0; i < smi->num_vlan_mc; i++) {
151 int used;
153 ret = rtl8366_mc_is_used(smi, i, &used);
154 if (ret)
155 return ret;
157 if (!used) {
158 /* Update the entry from the 4K table */
159 ret = smi->ops->get_vlan_4k(smi, vid, &vlan4k);
160 if (ret)
161 return ret;
163 vlanmc.vid = vid;
164 vlanmc.member = vlan4k.member;
165 vlanmc.untag = vlan4k.untag;
166 vlanmc.fid = vlan4k.fid;
167 ret = smi->ops->set_vlan_mc(smi, i, &vlanmc);
168 if (ret)
169 return ret;
171 ret = smi->ops->set_mc_index(smi, port, i);
172 return ret;
176 dev_err(smi->dev,
177 "all VLAN member configurations are in use\n");
179 return -ENOSPC;
181 EXPORT_SYMBOL_GPL(rtl8366_set_pvid);
183 int rtl8366_enable_vlan4k(struct realtek_smi *smi, bool enable)
185 int ret;
187 /* To enable 4k VLAN, ordinary VLAN must be enabled first,
188 * but if we disable 4k VLAN it is fine to leave ordinary
189 * VLAN enabled.
191 if (enable) {
192 /* Make sure VLAN is ON */
193 ret = smi->ops->enable_vlan(smi, true);
194 if (ret)
195 return ret;
197 smi->vlan_enabled = true;
200 ret = smi->ops->enable_vlan4k(smi, enable);
201 if (ret)
202 return ret;
204 smi->vlan4k_enabled = enable;
205 return 0;
207 EXPORT_SYMBOL_GPL(rtl8366_enable_vlan4k);
209 int rtl8366_enable_vlan(struct realtek_smi *smi, bool enable)
211 int ret;
213 ret = smi->ops->enable_vlan(smi, enable);
214 if (ret)
215 return ret;
217 smi->vlan_enabled = enable;
219 /* If we turn VLAN off, make sure that we turn off
220 * 4k VLAN as well, if that happened to be on.
222 if (!enable) {
223 smi->vlan4k_enabled = false;
224 ret = smi->ops->enable_vlan4k(smi, false);
227 return ret;
229 EXPORT_SYMBOL_GPL(rtl8366_enable_vlan);
231 int rtl8366_reset_vlan(struct realtek_smi *smi)
233 struct rtl8366_vlan_mc vlanmc;
234 int ret;
235 int i;
237 rtl8366_enable_vlan(smi, false);
238 rtl8366_enable_vlan4k(smi, false);
240 /* Clear the 16 VLAN member configurations */
241 vlanmc.vid = 0;
242 vlanmc.priority = 0;
243 vlanmc.member = 0;
244 vlanmc.untag = 0;
245 vlanmc.fid = 0;
246 for (i = 0; i < smi->num_vlan_mc; i++) {
247 ret = smi->ops->set_vlan_mc(smi, i, &vlanmc);
248 if (ret)
249 return ret;
252 return 0;
254 EXPORT_SYMBOL_GPL(rtl8366_reset_vlan);
256 int rtl8366_init_vlan(struct realtek_smi *smi)
258 int port;
259 int ret;
261 ret = rtl8366_reset_vlan(smi);
262 if (ret)
263 return ret;
265 /* Loop over the available ports, for each port, associate
266 * it with the VLAN (port+1)
268 for (port = 0; port < smi->num_ports; port++) {
269 u32 mask;
271 if (port == smi->cpu_port)
272 /* For the CPU port, make all ports members of this
273 * VLAN.
275 mask = GENMASK(smi->num_ports - 1, 0);
276 else
277 /* For all other ports, enable itself plus the
278 * CPU port.
280 mask = BIT(port) | BIT(smi->cpu_port);
282 /* For each port, set the port as member of VLAN (port+1)
283 * and untagged, except for the CPU port: the CPU port (5) is
284 * member of VLAN 6 and so are ALL the other ports as well.
285 * Use filter 0 (no filter).
287 dev_info(smi->dev, "VLAN%d port mask for port %d, %08x\n",
288 (port + 1), port, mask);
289 ret = rtl8366_set_vlan(smi, (port + 1), mask, mask, 0);
290 if (ret)
291 return ret;
293 dev_info(smi->dev, "VLAN%d port %d, PVID set to %d\n",
294 (port + 1), port, (port + 1));
295 ret = rtl8366_set_pvid(smi, port, (port + 1));
296 if (ret)
297 return ret;
300 return rtl8366_enable_vlan(smi, true);
302 EXPORT_SYMBOL_GPL(rtl8366_init_vlan);
304 int rtl8366_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering)
306 struct realtek_smi *smi = ds->priv;
307 struct rtl8366_vlan_4k vlan4k;
308 int ret;
310 if (!smi->ops->is_vlan_valid(smi, port))
311 return -EINVAL;
313 dev_info(smi->dev, "%s filtering on port %d\n",
314 vlan_filtering ? "enable" : "disable",
315 port);
317 /* TODO:
318 * The hardware support filter ID (FID) 0..7, I have no clue how to
319 * support this in the driver when the callback only says on/off.
321 ret = smi->ops->get_vlan_4k(smi, port, &vlan4k);
322 if (ret)
323 return ret;
325 /* Just set the filter to FID 1 for now then */
326 ret = rtl8366_set_vlan(smi, port,
327 vlan4k.member,
328 vlan4k.untag,
330 if (ret)
331 return ret;
333 return 0;
335 EXPORT_SYMBOL_GPL(rtl8366_vlan_filtering);
337 int rtl8366_vlan_prepare(struct dsa_switch *ds, int port,
338 const struct switchdev_obj_port_vlan *vlan)
340 struct realtek_smi *smi = ds->priv;
341 int ret;
343 if (!smi->ops->is_vlan_valid(smi, port))
344 return -EINVAL;
346 dev_info(smi->dev, "prepare VLANs %04x..%04x\n",
347 vlan->vid_begin, vlan->vid_end);
349 /* Enable VLAN in the hardware
350 * FIXME: what's with this 4k business?
351 * Just rtl8366_enable_vlan() seems inconclusive.
353 ret = rtl8366_enable_vlan4k(smi, true);
354 if (ret)
355 return ret;
357 return 0;
359 EXPORT_SYMBOL_GPL(rtl8366_vlan_prepare);
361 void rtl8366_vlan_add(struct dsa_switch *ds, int port,
362 const struct switchdev_obj_port_vlan *vlan)
364 bool untagged = !!(vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED);
365 bool pvid = !!(vlan->flags & BRIDGE_VLAN_INFO_PVID);
366 struct realtek_smi *smi = ds->priv;
367 u32 member = 0;
368 u32 untag = 0;
369 u16 vid;
370 int ret;
372 if (!smi->ops->is_vlan_valid(smi, port))
373 return;
375 dev_info(smi->dev, "add VLAN on port %d, %s, %s\n",
376 port,
377 untagged ? "untagged" : "tagged",
378 pvid ? " PVID" : "no PVID");
380 if (dsa_is_dsa_port(ds, port) || dsa_is_cpu_port(ds, port))
381 dev_err(smi->dev, "port is DSA or CPU port\n");
383 for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) {
384 int pvid_val = 0;
386 dev_info(smi->dev, "add VLAN %04x\n", vid);
387 member |= BIT(port);
389 if (untagged)
390 untag |= BIT(port);
392 /* To ensure that we have a valid MC entry for this VLAN,
393 * initialize the port VLAN ID here.
395 ret = rtl8366_get_pvid(smi, port, &pvid_val);
396 if (ret < 0) {
397 dev_err(smi->dev, "could not lookup PVID for port %d\n",
398 port);
399 return;
401 if (pvid_val == 0) {
402 ret = rtl8366_set_pvid(smi, port, vid);
403 if (ret < 0)
404 return;
408 ret = rtl8366_set_vlan(smi, port, member, untag, 0);
409 if (ret)
410 dev_err(smi->dev,
411 "failed to set up VLAN %04x",
412 vid);
414 EXPORT_SYMBOL_GPL(rtl8366_vlan_add);
416 int rtl8366_vlan_del(struct dsa_switch *ds, int port,
417 const struct switchdev_obj_port_vlan *vlan)
419 struct realtek_smi *smi = ds->priv;
420 u16 vid;
421 int ret;
423 dev_info(smi->dev, "del VLAN on port %d\n", port);
425 for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) {
426 int i;
428 dev_info(smi->dev, "del VLAN %04x\n", vid);
430 for (i = 0; i < smi->num_vlan_mc; i++) {
431 struct rtl8366_vlan_mc vlanmc;
433 ret = smi->ops->get_vlan_mc(smi, i, &vlanmc);
434 if (ret)
435 return ret;
437 if (vid == vlanmc.vid) {
438 /* clear VLAN member configurations */
439 vlanmc.vid = 0;
440 vlanmc.priority = 0;
441 vlanmc.member = 0;
442 vlanmc.untag = 0;
443 vlanmc.fid = 0;
445 ret = smi->ops->set_vlan_mc(smi, i, &vlanmc);
446 if (ret) {
447 dev_err(smi->dev,
448 "failed to remove VLAN %04x\n",
449 vid);
450 return ret;
452 break;
457 return 0;
459 EXPORT_SYMBOL_GPL(rtl8366_vlan_del);
461 void rtl8366_get_strings(struct dsa_switch *ds, int port, u32 stringset,
462 uint8_t *data)
464 struct realtek_smi *smi = ds->priv;
465 struct rtl8366_mib_counter *mib;
466 int i;
468 if (port >= smi->num_ports)
469 return;
471 for (i = 0; i < smi->num_mib_counters; i++) {
472 mib = &smi->mib_counters[i];
473 strncpy(data + i * ETH_GSTRING_LEN,
474 mib->name, ETH_GSTRING_LEN);
477 EXPORT_SYMBOL_GPL(rtl8366_get_strings);
479 int rtl8366_get_sset_count(struct dsa_switch *ds, int port, int sset)
481 struct realtek_smi *smi = ds->priv;
483 /* We only support SS_STATS */
484 if (sset != ETH_SS_STATS)
485 return 0;
486 if (port >= smi->num_ports)
487 return -EINVAL;
489 return smi->num_mib_counters;
491 EXPORT_SYMBOL_GPL(rtl8366_get_sset_count);
493 void rtl8366_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data)
495 struct realtek_smi *smi = ds->priv;
496 int i;
497 int ret;
499 if (port >= smi->num_ports)
500 return;
502 for (i = 0; i < smi->num_mib_counters; i++) {
503 struct rtl8366_mib_counter *mib;
504 u64 mibvalue = 0;
506 mib = &smi->mib_counters[i];
507 ret = smi->ops->get_mib_counter(smi, port, mib, &mibvalue);
508 if (ret) {
509 dev_err(smi->dev, "error reading MIB counter %s\n",
510 mib->name);
512 data[i] = mibvalue;
515 EXPORT_SYMBOL_GPL(rtl8366_get_ethtool_stats);