blob: e7965829af1dc30383f5ea48bba6d2afc1515dc8 [file] [log] [blame]
developer69bcd592024-03-25 14:26:39 +08001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (c) 2023 Airoha Inc.
4 * Author: Min Yao <min.yao@airoha.com>
5 */
6
7#include <linux/if.h>
8#include <linux/list.h>
9#include <linux/if_ether.h>
10#include <linux/skbuff.h>
11#include <linux/netdevice.h>
12#include <linux/netlink.h>
13#include <linux/bitops.h>
14#include <net/genetlink.h>
15#include <linux/delay.h>
16#include <linux/phy.h>
17#include <linux/netdevice.h>
18#include <linux/etherdevice.h>
19#include <linux/lockdep.h>
20#include <linux/workqueue.h>
21#include <linux/of_device.h>
22
23#include "an8855.h"
24#include "an8855_swconfig.h"
25#include "an8855_regs.h"
26
27#define AN8855_PORT_MIB_TXB_ID 19 /* TxByte */
28#define AN8855_PORT_MIB_RXB_ID 40 /* RxByte */
29
30#define MIB_DESC(_s, _o, _n) \
31 { \
32 .size = (_s), \
33 .offset = (_o), \
34 .name = (_n), \
35 }
36
37struct an8855_mib_desc {
38 unsigned int size;
39 unsigned int offset;
40 const char *name;
41};
42
43static const struct an8855_mib_desc an8855_mibs[] = {
44 MIB_DESC(1, STATS_TDPC, "TxDrop"),
45 MIB_DESC(1, STATS_TCRC, "TxCRC"),
46 MIB_DESC(1, STATS_TUPC, "TxUni"),
47 MIB_DESC(1, STATS_TMPC, "TxMulti"),
48 MIB_DESC(1, STATS_TBPC, "TxBroad"),
49 MIB_DESC(1, STATS_TCEC, "TxCollision"),
50 MIB_DESC(1, STATS_TSCEC, "TxSingleCol"),
51 MIB_DESC(1, STATS_TMCEC, "TxMultiCol"),
52 MIB_DESC(1, STATS_TDEC, "TxDefer"),
53 MIB_DESC(1, STATS_TLCEC, "TxLateCol"),
54 MIB_DESC(1, STATS_TXCEC, "TxExcCol"),
55 MIB_DESC(1, STATS_TPPC, "TxPause"),
56 MIB_DESC(1, STATS_TL64PC, "Tx64Byte"),
57 MIB_DESC(1, STATS_TL65PC, "Tx65Byte"),
58 MIB_DESC(1, STATS_TL128PC, "Tx128Byte"),
59 MIB_DESC(1, STATS_TL256PC, "Tx256Byte"),
60 MIB_DESC(1, STATS_TL512PC, "Tx512Byte"),
61 MIB_DESC(1, STATS_TL1024PC, "Tx1024Byte"),
62 MIB_DESC(1, STATS_TL1519PC, "Tx1519Byte"),
63 MIB_DESC(2, STATS_TOC, "TxByte"),
64 MIB_DESC(1, STATS_TODPC, "TxOverSize"),
65 MIB_DESC(2, STATS_TOC2, "SecondaryTxByte"),
66 MIB_DESC(1, STATS_RDPC, "RxDrop"),
67 MIB_DESC(1, STATS_RFPC, "RxFiltered"),
68 MIB_DESC(1, STATS_RUPC, "RxUni"),
69 MIB_DESC(1, STATS_RMPC, "RxMulti"),
70 MIB_DESC(1, STATS_RBPC, "RxBroad"),
71 MIB_DESC(1, STATS_RAEPC, "RxAlignErr"),
72 MIB_DESC(1, STATS_RCEPC, "RxCRC"),
73 MIB_DESC(1, STATS_RUSPC, "RxUnderSize"),
74 MIB_DESC(1, STATS_RFEPC, "RxFragment"),
75 MIB_DESC(1, STATS_ROSPC, "RxOverSize"),
76 MIB_DESC(1, STATS_RJEPC, "RxJabber"),
77 MIB_DESC(1, STATS_RPPC, "RxPause"),
78 MIB_DESC(1, STATS_RL64PC, "Rx64Byte"),
79 MIB_DESC(1, STATS_RL65PC, "Rx65Byte"),
80 MIB_DESC(1, STATS_RL128PC, "Rx128Byte"),
81 MIB_DESC(1, STATS_RL256PC, "Rx256Byte"),
82 MIB_DESC(1, STATS_RL512PC, "Rx512Byte"),
83 MIB_DESC(1, STATS_RL1024PC, "Rx1024Byte"),
84 MIB_DESC(2, STATS_ROC, "RxByte"),
85 MIB_DESC(1, STATS_RDPC_CTRL, "RxCtrlDrop"),
86 MIB_DESC(1, STATS_RDPC_ING, "RxIngDrop"),
87 MIB_DESC(1, STATS_RDPC_ARL, "RxARLDrop"),
88 MIB_DESC(1, STATS_RDPC_FC, "RxFCDrop"),
89 MIB_DESC(1, STATS_RDPC_WRED, "RxWREDDrop"),
90 MIB_DESC(1, STATS_RDPC_MIR, "RxMIRDrop"),
91 MIB_DESC(2, STATS_ROC2, "SecondaryRxByte"),
92 MIB_DESC(1, STATS_RSFSPC, "RxsFlowSampling"),
93 MIB_DESC(1, STATS_RSFTPC, "RxsFlowTotal"),
94 MIB_DESC(1, STATS_RXCDPC, "RxPortDrop"),
95};
96
97enum {
98 /* Global attributes. */
99 AN8855_ATTR_ENABLE_VLAN,
100};
101
102static int an8855_get_vlan_enable(struct switch_dev *dev,
103 const struct switch_attr *attr,
104 struct switch_val *val)
105{
106 struct gsw_an8855 *gsw = container_of(dev, struct gsw_an8855, swdev);
107
108 val->value.i = gsw->global_vlan_enable;
109
110 return 0;
111}
112
113static int an8855_set_vlan_enable(struct switch_dev *dev,
114 const struct switch_attr *attr,
115 struct switch_val *val)
116{
117 struct gsw_an8855 *gsw = container_of(dev, struct gsw_an8855, swdev);
118
119 gsw->global_vlan_enable = val->value.i != 0;
120
121 return 0;
122}
123
124static int an8855_get_port_pvid(struct switch_dev *dev, int port, int *val)
125{
126 struct gsw_an8855 *gsw = container_of(dev, struct gsw_an8855, swdev);
127
128 if (port >= AN8855_NUM_PORTS)
129 return -EINVAL;
130
131 *val = an8855_reg_read(gsw, PVID(port));
132 *val &= GRP_PORT_VID_M;
133
134 return 0;
135}
136
137static int an8855_set_port_pvid(struct switch_dev *dev, int port, int pvid)
138{
139 struct gsw_an8855 *gsw = container_of(dev, struct gsw_an8855, swdev);
140
141 if (port >= AN8855_NUM_PORTS)
142 return -EINVAL;
143
144 if (pvid < AN8855_MIN_VID || pvid > AN8855_MAX_VID)
145 return -EINVAL;
146
147 gsw->port_entries[port].pvid = pvid;
148
149 return 0;
150}
151
152static int an8855_get_vlan_ports(struct switch_dev *dev, struct switch_val *val)
153{
154 struct gsw_an8855 *gsw = container_of(dev, struct gsw_an8855, swdev);
155 u32 member;
156 u32 etags;
157 int i;
158
159 val->len = 0;
160
161 if (val->port_vlan >= AN8855_NUM_VLANS)
162 return -EINVAL;
163
164 an8855_vlan_ctrl(gsw, VTCR_READ_VLAN_ENTRY, val->port_vlan);
165
166 member = an8855_reg_read(gsw, VARD0);
167 member &= PORT_MEM_M;
168 member >>= PORT_MEM_S;
169 member |= ((an8855_reg_read(gsw, VARD1) & 0x1) << 6);
170
171 etags = an8855_reg_read(gsw, VARD0) & ETAG_M;
172
173 for (i = 0; i < AN8855_NUM_PORTS; i++) {
174 struct switch_port *p;
175 int etag;
176
177 if (!(member & BIT(i)))
178 continue;
179
180 p = &val->value.ports[val->len++];
181 p->id = i;
182
183 etag = (etags >> PORT_ETAG_S(i)) & PORT_ETAG_M;
184
185 if (etag == ETAG_CTRL_TAG)
186 p->flags |= BIT(SWITCH_PORT_FLAG_TAGGED);
187 else if (etag != ETAG_CTRL_UNTAG)
188 dev_info(gsw->dev,
189 "vlan egress tag control neither untag nor tag.\n");
190 }
191
192 return 0;
193}
194
195static int an8855_set_vlan_ports(struct switch_dev *dev, struct switch_val *val)
196{
197 struct gsw_an8855 *gsw = container_of(dev, struct gsw_an8855, swdev);
198 u8 member = 0;
199 u8 etags = 0;
200 int i;
201
202 if (val->port_vlan >= AN8855_NUM_VLANS ||
203 val->len > AN8855_NUM_PORTS)
204 return -EINVAL;
205
206 for (i = 0; i < val->len; i++) {
207 struct switch_port *p = &val->value.ports[i];
208
209 if (p->id >= AN8855_NUM_PORTS)
210 return -EINVAL;
211
212 member |= BIT(p->id);
213
214 if (p->flags & BIT(SWITCH_PORT_FLAG_TAGGED))
215 etags |= BIT(p->id);
216 }
217
218 gsw->vlan_entries[val->port_vlan].member = member;
219 gsw->vlan_entries[val->port_vlan].etags = etags;
220
221 return 0;
222}
223
224static int an8855_set_vid(struct switch_dev *dev,
225 const struct switch_attr *attr,
226 struct switch_val *val)
227{
228 struct gsw_an8855 *gsw = container_of(dev, struct gsw_an8855, swdev);
229 int vlan;
230 u16 vid;
231
232 vlan = val->port_vlan;
233 vid = (u16)val->value.i;
234
235 if (vlan < 0 || vlan >= AN8855_NUM_VLANS)
236 return -EINVAL;
237
238 if (vid > AN8855_MAX_VID)
239 return -EINVAL;
240
241 gsw->vlan_entries[vlan].vid = vid;
242 return 0;
243}
244
245static int an8855_get_vid(struct switch_dev *dev,
246 const struct switch_attr *attr,
247 struct switch_val *val)
248{
249 val->value.i = val->port_vlan;
250 return 0;
251}
252
253static int an8855_get_port_link(struct switch_dev *dev, int port,
254 struct switch_port_link *link)
255{
256 struct gsw_an8855 *gsw = container_of(dev, struct gsw_an8855, swdev);
257 u32 speed, pmsr;
258
259 if (port < 0 || port >= AN8855_NUM_PORTS)
260 return -EINVAL;
261
262 pmsr = an8855_reg_read(gsw, PMSR(port));
263
264 link->link = pmsr & MAC_LNK_STS;
265 link->duplex = pmsr & MAC_DPX_STS;
266 speed = (pmsr & MAC_SPD_STS_M) >> MAC_SPD_STS_S;
267
268 switch (speed) {
269 case MAC_SPD_10:
270 link->speed = SWITCH_PORT_SPEED_10;
271 break;
272 case MAC_SPD_100:
273 link->speed = SWITCH_PORT_SPEED_100;
274 break;
275 case MAC_SPD_1000:
276 link->speed = SWITCH_PORT_SPEED_1000;
277 break;
278 case MAC_SPD_2500:
279 /* TODO: swconfig has no support for 2500 now */
280 link->speed = SWITCH_PORT_SPEED_UNKNOWN;
281 break;
282 }
283
284 return 0;
285}
286
287static int an8855_set_port_link(struct switch_dev *dev, int port,
288 struct switch_port_link *link)
289{
290#ifndef MODULE
291 if (port >= AN8855_NUM_PHYS)
292 return -EINVAL;
293
294 return switch_generic_set_link(dev, port, link);
295#else
296 return -ENOTSUPP;
297#endif
298}
299
300static u64 get_mib_counter(struct gsw_an8855 *gsw, int i, int port)
301{
302 unsigned int offset;
303 u64 lo, hi, hi2;
304
305 offset = an8855_mibs[i].offset;
306
307 if (an8855_mibs[i].size == 1)
308 return an8855_reg_read(gsw, MIB_COUNTER_REG(port, offset));
309
310 do {
311 hi = an8855_reg_read(gsw, MIB_COUNTER_REG(port, offset + 4));
312 lo = an8855_reg_read(gsw, MIB_COUNTER_REG(port, offset));
313 hi2 = an8855_reg_read(gsw, MIB_COUNTER_REG(port, offset + 4));
314 } while (hi2 != hi);
315
316 return (hi << 32) | lo;
317}
318
319static int an8855_get_port_mib(struct switch_dev *dev,
320 const struct switch_attr *attr,
321 struct switch_val *val)
322{
323 static char buf[4096];
324 struct gsw_an8855 *gsw = container_of(dev, struct gsw_an8855, swdev);
325 int i, len = 0;
326
327 if (val->port_vlan >= AN8855_NUM_PORTS)
328 return -EINVAL;
329
330 len += snprintf(buf + len, sizeof(buf) - len,
331 "Port %d MIB counters\n", val->port_vlan);
332
333 for (i = 0; i < ARRAY_SIZE(an8855_mibs); ++i) {
334 u64 counter;
335
336 len += snprintf(buf + len, sizeof(buf) - len,
337 "%-11s: ", an8855_mibs[i].name);
338 counter = get_mib_counter(gsw, i, val->port_vlan);
339 len += snprintf(buf + len, sizeof(buf) - len, "%llu\n",
340 counter);
341 }
342
343 val->value.s = buf;
344 val->len = len;
345 return 0;
346}
347
348static int an8855_get_port_stats(struct switch_dev *dev, int port,
349 struct switch_port_stats *stats)
350{
351 struct gsw_an8855 *gsw = container_of(dev, struct gsw_an8855, swdev);
352
353 if (port < 0 || port >= AN8855_NUM_PORTS)
354 return -EINVAL;
355
356 stats->tx_bytes = get_mib_counter(gsw, AN8855_PORT_MIB_TXB_ID, port);
357 stats->rx_bytes = get_mib_counter(gsw, AN8855_PORT_MIB_RXB_ID, port);
358
359 return 0;
360}
361
362static void an8855_port_isolation(struct gsw_an8855 *gsw)
363{
364 int i;
365
366 for (i = 0; i < AN8855_NUM_PORTS; i++)
367 an8855_reg_write(gsw, PORTMATRIX(i),
368 BIT(gsw->cpu_port));
369
370 an8855_reg_write(gsw, PORTMATRIX(gsw->cpu_port), PORT_MATRIX_M);
371
372 for (i = 0; i < AN8855_NUM_PORTS; i++) {
373 u32 pvc_mode = 0x8100 << STAG_VPID_S;
374
375 if (gsw->port5_cfg.stag_on && i == 5)
376 pvc_mode |= PVC_PORT_STAG | PVC_STAG_REPLACE;
377 else
378 pvc_mode |= (VA_TRANSPARENT_PORT << VLAN_ATTR_S);
379
380 an8855_reg_write(gsw, PVC(i), pvc_mode);
381 }
382}
383
384static int an8855_apply_config(struct switch_dev *dev)
385{
386 struct gsw_an8855 *gsw = container_of(dev, struct gsw_an8855, swdev);
387
388 if (!gsw->global_vlan_enable) {
389 an8855_port_isolation(gsw);
390 return 0;
391 }
392
393 an8855_apply_vlan_config(gsw);
394
395 return 0;
396}
397
398static int an8855_reset_switch(struct switch_dev *dev)
399{
400 struct gsw_an8855 *gsw = container_of(dev, struct gsw_an8855, swdev);
401 int i;
402
403 memset(gsw->port_entries, 0, sizeof(gsw->port_entries));
404 memset(gsw->vlan_entries, 0, sizeof(gsw->vlan_entries));
405
406 /* set default vid of each vlan to the same number of vlan, so the vid
407 * won't need be set explicitly.
408 */
409 for (i = 0; i < AN8855_NUM_VLANS; i++)
410 gsw->vlan_entries[i].vid = i;
411
412 return 0;
413}
414
415static int an8855_phy_read16(struct switch_dev *dev, int addr, u8 reg,
416 u16 *value)
417{
418 struct gsw_an8855 *gsw = container_of(dev, struct gsw_an8855, swdev);
419
420 *value = gsw->mii_read(gsw, addr, reg);
421
422 return 0;
423}
424
425static int an8855_phy_write16(struct switch_dev *dev, int addr, u8 reg,
426 u16 value)
427{
428 struct gsw_an8855 *gsw = container_of(dev, struct gsw_an8855, swdev);
429
430 gsw->mii_write(gsw, addr, reg, value);
431
432 return 0;
433}
434
435static const struct switch_attr an8855_global[] = {
436 {
437 .type = SWITCH_TYPE_INT,
438 .name = "enable_vlan",
439 .description = "VLAN mode (1:enabled)",
440 .max = 1,
441 .id = AN8855_ATTR_ENABLE_VLAN,
442 .get = an8855_get_vlan_enable,
443 .set = an8855_set_vlan_enable,
444 }
445};
446
447static const struct switch_attr an8855_port[] = {
448 {
449 .type = SWITCH_TYPE_STRING,
450 .name = "mib",
451 .description = "Get MIB counters for port",
452 .get = an8855_get_port_mib,
453 .set = NULL,
454 },
455};
456
457static const struct switch_attr an8855_vlan[] = {
458 {
459 .type = SWITCH_TYPE_INT,
460 .name = "vid",
461 .description = "VLAN ID (0-4094)",
462 .set = an8855_set_vid,
463 .get = an8855_get_vid,
464 .max = 4094,
465 },
466};
467
468static const struct switch_dev_ops an8855_swdev_ops = {
469 .attr_global = {
470 .attr = an8855_global,
471 .n_attr = ARRAY_SIZE(an8855_global),
472 },
473 .attr_port = {
474 .attr = an8855_port,
475 .n_attr = ARRAY_SIZE(an8855_port),
476 },
477 .attr_vlan = {
478 .attr = an8855_vlan,
479 .n_attr = ARRAY_SIZE(an8855_vlan),
480 },
481 .get_vlan_ports = an8855_get_vlan_ports,
482 .set_vlan_ports = an8855_set_vlan_ports,
483 .get_port_pvid = an8855_get_port_pvid,
484 .set_port_pvid = an8855_set_port_pvid,
485 .get_port_link = an8855_get_port_link,
486 .set_port_link = an8855_set_port_link,
487 .get_port_stats = an8855_get_port_stats,
488 .apply_config = an8855_apply_config,
489 .reset_switch = an8855_reset_switch,
490 .phy_read16 = an8855_phy_read16,
491 .phy_write16 = an8855_phy_write16,
492};
493
494int an8855_swconfig_init(struct gsw_an8855 *gsw)
495{
496 struct device_node *np = gsw->dev->of_node;
497 struct switch_dev *swdev;
498 int ret;
499
500 if (of_property_read_u32(np, "airoha,cpuport", &gsw->cpu_port))
501 gsw->cpu_port = AN8855_DFL_CPU_PORT;
502
503 swdev = &gsw->swdev;
504
505 swdev->name = gsw->name;
506 swdev->alias = gsw->name;
507 swdev->cpu_port = gsw->cpu_port;
508 swdev->ports = AN8855_NUM_PORTS;
509 swdev->vlans = AN8855_NUM_VLANS;
510 swdev->ops = &an8855_swdev_ops;
511
512 ret = register_switch(swdev, NULL);
513 if (ret) {
514 dev_notice(gsw->dev, "Failed to register switch %s\n",
515 swdev->name);
516 return ret;
517 }
518
519 an8855_apply_config(swdev);
520
521 return 0;
522}
523
524void an8855_swconfig_destroy(struct gsw_an8855 *gsw)
525{
526 unregister_switch(&gsw->swdev);
527}