mediatek: add support for rtl8367c
[openwrt/staging/jow.git] / target / linux / mediatek / files-5.4 / drivers / net / phy / rtk / rtl8367s.c
1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
13
14 #include <linux/kernel.h>
15 #include <linux/module.h>
16 #include <linux/init.h>
17 #include <linux/device.h>
18 #include <linux/delay.h>
19 #include <linux/skbuff.h>
20 #include <linux/switch.h>
21
22 //include from rtl8367c dir
23 #include "./rtl8367c/include/rtk_switch.h"
24 #include "./rtl8367c/include/vlan.h"
25 #include "./rtl8367c/include/stat.h"
26 #include "./rtl8367c/include/port.h"
27
28 #define RTL8367C_SW_CPU_PORT 6
29
30 //RTL8367C_PHY_PORT_NUM + ext0 + ext1
31 #define RTL8367C_NUM_PORTS 7
32 #define RTL8367C_NUM_VIDS 4096
33
34 struct rtl8367_priv {
35 struct switch_dev swdev;
36 bool global_vlan_enable;
37 };
38
39 struct rtl8367_mib_counter {
40 const char *name;
41 };
42
43 struct rtl8367_vlan_info {
44 unsigned short vid;
45 unsigned int untag;
46 unsigned int member;
47 unsigned char fid;
48 };
49
50 struct rtl8367_priv rtl8367_priv_data;
51
52 unsigned int rtl8367c_port_id[RTL8367C_NUM_PORTS]={0,1,2,3,4,EXT_PORT1,EXT_PORT0};
53
54 void (*rtl8367_switch_reset_func)(void)=NULL;
55
56 static struct rtl8367_mib_counter rtl8367c_mib_counters[] = {
57 {"ifInOctets"},
58 {"dot3StatsFCSErrors"},
59 {"dot3StatsSymbolErrors"},
60 {"dot3InPauseFrames"},
61 {"dot3ControlInUnknownOpcodes"},
62 {"etherStatsFragments"},
63 {"etherStatsJabbers"},
64 {"ifInUcastPkts"},
65 {"etherStatsDropEvents"},
66 {"etherStatsOctets"},
67 {"etherStatsUndersizePkts"},
68 {"etherStatsOversizePkts"},
69 {"etherStatsPkts64Octets"},
70 {"etherStatsPkts65to127Octets"},
71 {"etherStatsPkts128to255Octets"},
72 {"etherStatsPkts256to511Octets"},
73 {"etherStatsPkts512to1023Octets"},
74 {"etherStatsPkts1024toMaxOctets"},
75 {"etherStatsMcastPkts"},
76 {"etherStatsBcastPkts"},
77 {"ifOutOctets"},
78 {"dot3StatsSingleCollisionFrames"},
79 {"dot3StatsMultipleCollisionFrames"},
80 {"dot3StatsDeferredTransmissions"},
81 {"dot3StatsLateCollisions"},
82 {"etherStatsCollisions"},
83 {"dot3StatsExcessiveCollisions"},
84 {"dot3OutPauseFrames"},
85 {"dot1dBasePortDelayExceededDiscards"},
86 {"dot1dTpPortInDiscards"},
87 {"ifOutUcastPkts"},
88 {"ifOutMulticastPkts"},
89 {"ifOutBrocastPkts"},
90 {"outOampduPkts"},
91 {"inOampduPkts"},
92 {"pktgenPkts"},
93 {"inMldChecksumError"},
94 {"inIgmpChecksumError"},
95 {"inMldSpecificQuery"},
96 {"inMldGeneralQuery"},
97 {"inIgmpSpecificQuery"},
98 {"inIgmpGeneralQuery"},
99 {"inMldLeaves"},
100 {"inIgmpLeaves"},
101 {"inIgmpJoinsSuccess"},
102 {"inIgmpJoinsFail"},
103 {"inMldJoinsSuccess"},
104 {"inMldJoinsFail"},
105 {"inReportSuppressionDrop"},
106 {"inLeaveSuppressionDrop"},
107 {"outIgmpReports"},
108 {"outIgmpLeaves"},
109 {"outIgmpGeneralQuery"},
110 {"outIgmpSpecificQuery"},
111 {"outMldReports"},
112 {"outMldLeaves"},
113 {"outMldGeneralQuery"},
114 {"outMldSpecificQuery"},
115 {"inKnownMulticastPkts"},
116 {"ifInMulticastPkts"},
117 {"ifInBroadcastPkts"},
118 {"ifOutDiscards"}
119 };
120
121 /*rtl8367c proprietary switch API wrapper */
122 static inline unsigned int rtl8367c_sw_to_phy_port(int port)
123 {
124 return rtl8367c_port_id[port];
125 }
126
127 static inline unsigned int rtl8367c_portmask_phy_to_sw(rtk_portmask_t phy_portmask)
128 {
129 int i;
130 for (i = 0; i < RTL8367C_NUM_PORTS; i++) {
131 if(RTK_PORTMASK_IS_PORT_SET(phy_portmask,rtl8367c_sw_to_phy_port(i))) {
132 RTK_PORTMASK_PORT_CLEAR(phy_portmask,rtl8367c_sw_to_phy_port(i));
133 RTK_PORTMASK_PORT_SET(phy_portmask,i);
134 }
135
136 }
137 return (unsigned int)phy_portmask.bits[0];
138 }
139
140 static int rtl8367c_reset_mibs(void)
141 {
142 return rtk_stat_global_reset();
143 }
144
145 static int rtl8367c_reset_port_mibs(int port)
146 {
147
148 return rtk_stat_port_reset(rtl8367c_sw_to_phy_port(port));
149 }
150
151 static int rtl8367c_get_mibs_num(void)
152 {
153 return ARRAY_SIZE(rtl8367c_mib_counters);
154 }
155
156 static const char *rtl8367c_get_mib_name(int idx)
157 {
158
159 return rtl8367c_mib_counters[idx].name;
160 }
161
162 static int rtl8367c_get_port_mib_counter(int idx, int port, unsigned long long *counter)
163 {
164 return rtk_stat_port_get(rtl8367c_sw_to_phy_port(port), idx, counter);
165 }
166
167 static int rtl8367c_is_vlan_valid(unsigned int vlan)
168 {
169 unsigned max = RTL8367C_NUM_VIDS;
170
171 if (vlan == 0 || vlan >= max)
172 return 0;
173
174 return 1;
175 }
176
177 static int rtl8367c_get_vlan( unsigned short vid, struct rtl8367_vlan_info *vlan)
178 {
179 rtk_vlan_cfg_t vlan_cfg;
180
181 memset(vlan, '\0', sizeof(struct rtl8367_vlan_info));
182
183 if (vid >= RTL8367C_NUM_VIDS)
184 return -EINVAL;
185
186 if(rtk_vlan_get(vid,&vlan_cfg))
187 return -EINVAL;
188
189 vlan->vid = vid;
190 vlan->member = rtl8367c_portmask_phy_to_sw(vlan_cfg.mbr);
191 vlan->untag = rtl8367c_portmask_phy_to_sw(vlan_cfg.untag);
192 vlan->fid = vlan_cfg.fid_msti;
193
194 return 0;
195 }
196
197 static int rtl8367c_set_vlan( unsigned short vid, u32 mbr, u32 untag, u8 fid)
198 {
199 rtk_vlan_cfg_t vlan_cfg;
200 int i;
201
202 memset(&vlan_cfg, 0x00, sizeof(rtk_vlan_cfg_t));
203
204 for (i = 0; i < RTL8367C_NUM_PORTS; i++) {
205 if (mbr & (1 << i)) {
206 RTK_PORTMASK_PORT_SET(vlan_cfg.mbr, rtl8367c_sw_to_phy_port(i));
207 if(untag & (1 << i))
208 RTK_PORTMASK_PORT_SET(vlan_cfg.untag, rtl8367c_sw_to_phy_port(i));
209 }
210 }
211 vlan_cfg.fid_msti=fid;
212 vlan_cfg.ivl_en = 1;
213 return rtk_vlan_set(vid, &vlan_cfg);
214 }
215
216
217 static int rtl8367c_get_pvid( int port, int *pvid)
218 {
219 u32 prio=0;
220
221 if (port >= RTL8367C_NUM_PORTS)
222 return -EINVAL;
223
224 return rtk_vlan_portPvid_get(rtl8367c_sw_to_phy_port(port),pvid,&prio);
225 }
226
227
228 static int rtl8367c_set_pvid( int port, int pvid)
229 {
230 u32 prio=0;
231
232 if (port >= RTL8367C_NUM_PORTS)
233 return -EINVAL;
234
235 return rtk_vlan_portPvid_set(rtl8367c_sw_to_phy_port(port),pvid,prio);
236 }
237
238 static int rtl8367c_get_port_link(int port, int *link, int *speed, int *duplex)
239 {
240
241 if(rtk_port_phyStatus_get(rtl8367c_sw_to_phy_port(port),(rtk_port_linkStatus_t *)link,
242 (rtk_port_speed_t *)speed,(rtk_port_duplex_t *)duplex))
243 return -EINVAL;
244
245 return 0;
246 }
247
248 /*common rtl8367 swconfig entry API*/
249
250 static int
251 rtl8367_sw_set_vlan_enable(struct switch_dev *dev,
252 const struct switch_attr *attr,
253 struct switch_val *val)
254 {
255 struct rtl8367_priv *priv = container_of(dev, struct rtl8367_priv, swdev);
256
257 priv->global_vlan_enable = val->value.i ;
258
259 return 0;
260 }
261
262 static int
263 rtl8367_sw_get_vlan_enable(struct switch_dev *dev,
264 const struct switch_attr *attr,
265 struct switch_val *val)
266 {
267 struct rtl8367_priv *priv = container_of(dev, struct rtl8367_priv, swdev);
268
269 val->value.i = priv->global_vlan_enable;
270
271 return 0;
272 }
273
274 static int rtl8367_sw_reset_mibs(struct switch_dev *dev,
275 const struct switch_attr *attr,
276 struct switch_val *val)
277 {
278 return rtl8367c_reset_mibs();
279 }
280
281
282 static int rtl8367_sw_reset_port_mibs(struct switch_dev *dev,
283 const struct switch_attr *attr,
284 struct switch_val *val)
285 {
286 int port;
287
288 port = val->port_vlan;
289 if (port >= RTL8367C_NUM_PORTS)
290 return -EINVAL;
291
292 return rtl8367c_reset_port_mibs(port);
293 }
294
295 static int rtl8367_sw_get_port_mib(struct switch_dev *dev,
296 const struct switch_attr *attr,
297 struct switch_val *val)
298 {
299 int i, len = 0;
300 unsigned long long counter = 0;
301 static char mib_buf[4096];
302
303 if (val->port_vlan >= RTL8367C_NUM_PORTS)
304 return -EINVAL;
305
306 len += snprintf(mib_buf + len, sizeof(mib_buf) - len,
307 "Port %d MIB counters\n",
308 val->port_vlan);
309
310 for (i = 0; i <rtl8367c_get_mibs_num(); ++i) {
311 len += snprintf(mib_buf + len, sizeof(mib_buf) - len,
312 "%-36s: ",rtl8367c_get_mib_name(i));
313 if (!rtl8367c_get_port_mib_counter(i, val->port_vlan,
314 &counter))
315 len += snprintf(mib_buf + len, sizeof(mib_buf) - len,
316 "%llu\n", counter);
317 else
318 len += snprintf(mib_buf + len, sizeof(mib_buf) - len,
319 "%s\n", "N/A");
320 }
321
322 val->value.s = mib_buf;
323 val->len = len;
324 return 0;
325 }
326
327
328 static int rtl8367_sw_get_vlan_info(struct switch_dev *dev,
329 const struct switch_attr *attr,
330 struct switch_val *val)
331 {
332 int i;
333 u32 len = 0;
334 struct rtl8367_vlan_info vlan;
335 static char vlan_buf[256];
336 int err;
337
338 if (!rtl8367c_is_vlan_valid(val->port_vlan))
339 return -EINVAL;
340
341 memset(vlan_buf, '\0', sizeof(vlan_buf));
342
343 err = rtl8367c_get_vlan(val->port_vlan, &vlan);
344 if (err)
345 return err;
346
347 len += snprintf(vlan_buf + len, sizeof(vlan_buf) - len,
348 "VLAN %d: Ports: '", vlan.vid);
349
350 for (i = 0; i <RTL8367C_NUM_PORTS; i++) {
351 if (!(vlan.member & (1 << i)))
352 continue;
353
354 len += snprintf(vlan_buf + len, sizeof(vlan_buf) - len, "%d%s", i,
355 (vlan.untag & (1 << i)) ? "" : "t");
356 }
357
358 len += snprintf(vlan_buf + len, sizeof(vlan_buf) - len,
359 "', members=%04x, untag=%04x, fid=%u",
360 vlan.member, vlan.untag, vlan.fid);
361
362 val->value.s = vlan_buf;
363 val->len = len;
364
365 return 0;
366 }
367
368
369 static int rtl8367_sw_get_vlan_ports(struct switch_dev *dev, struct switch_val *val)
370 {
371 struct switch_port *port;
372 struct rtl8367_vlan_info vlan;
373 int i;
374
375 if (!rtl8367c_is_vlan_valid(val->port_vlan))
376 return -EINVAL;
377
378 if(rtl8367c_get_vlan(val->port_vlan, &vlan))
379 return -EINVAL;
380
381 port = &val->value.ports[0];
382 val->len = 0;
383 for (i = 0; i <RTL8367C_NUM_PORTS ; i++) {
384 if (!(vlan.member & BIT(i)))
385 continue;
386
387 port->id = i;
388 port->flags = (vlan.untag & BIT(i)) ?
389 0 : BIT(SWITCH_PORT_FLAG_TAGGED);
390 val->len++;
391 port++;
392 }
393 return 0;
394 }
395
396
397 static int rtl8367_sw_set_vlan_ports(struct switch_dev *dev, struct switch_val *val)
398 {
399 struct switch_port *port;
400 u32 member = 0;
401 u32 untag = 0;
402 u8 fid=0;
403 int err;
404 int i;
405
406 if (!rtl8367c_is_vlan_valid(val->port_vlan))
407 return -EINVAL;
408
409 port = &val->value.ports[0];
410 for (i = 0; i < val->len; i++, port++) {
411 int pvid = 0;
412 member |= BIT(port->id);
413
414 if (!(port->flags & BIT(SWITCH_PORT_FLAG_TAGGED)))
415 untag |= BIT(port->id);
416
417 /*
418 * To ensure that we have a valid MC entry for this VLAN,
419 * initialize the port VLAN ID here.
420 */
421 err = rtl8367c_get_pvid(port->id, &pvid);
422 if (err < 0)
423 return err;
424 if (pvid == 0) {
425 err = rtl8367c_set_pvid(port->id, val->port_vlan);
426 if (err < 0)
427 return err;
428 }
429 }
430
431 //pr_info("[%s] vid=%d , mem=%x,untag=%x,fid=%d \n",__func__,val->port_vlan,member,untag,fid);
432
433 return rtl8367c_set_vlan(val->port_vlan, member, untag, fid);
434
435 }
436
437
438 static int rtl8367_sw_get_port_pvid(struct switch_dev *dev, int port, int *val)
439 {
440 return rtl8367c_get_pvid(port, val);
441 }
442
443
444 static int rtl8367_sw_set_port_pvid(struct switch_dev *dev, int port, int val)
445 {
446 return rtl8367c_set_pvid(port, val);
447 }
448
449
450 static int rtl8367_sw_reset_switch(struct switch_dev *dev)
451 {
452 if(rtl8367_switch_reset_func)
453 (*rtl8367_switch_reset_func)();
454 else
455 printk("rest switch is not supported\n");
456
457 return 0;
458 }
459
460 static int rtl8367_sw_get_port_link(struct switch_dev *dev, int port,
461 struct switch_port_link *link)
462 {
463 int speed;
464
465 if (port >= RTL8367C_NUM_PORTS)
466 return -EINVAL;
467
468 if(rtl8367c_get_port_link(port,(int *)&link->link,(int *)&speed,(int *)&link->duplex))
469 return -EINVAL;
470
471 if (!link->link)
472 return 0;
473
474 switch (speed) {
475 case 0:
476 link->speed = SWITCH_PORT_SPEED_10;
477 break;
478 case 1:
479 link->speed = SWITCH_PORT_SPEED_100;
480 break;
481 case 2:
482 link->speed = SWITCH_PORT_SPEED_1000;
483 break;
484 default:
485 link->speed = SWITCH_PORT_SPEED_UNKNOWN;
486 break;
487 }
488
489 return 0;
490 }
491
492
493 static struct switch_attr rtl8367_globals[] = {
494 {
495 .type = SWITCH_TYPE_INT,
496 .name = "enable_vlan",
497 .description = "Enable VLAN mode",
498 .set = rtl8367_sw_set_vlan_enable,
499 .get = rtl8367_sw_get_vlan_enable,
500 .max = 1,
501 }, {
502 .type = SWITCH_TYPE_NOVAL,
503 .name = "reset_mibs",
504 .description = "Reset all MIB counters",
505 .set = rtl8367_sw_reset_mibs,
506 }
507 };
508
509 static struct switch_attr rtl8367_port[] = {
510 {
511 .type = SWITCH_TYPE_NOVAL,
512 .name = "reset_mib",
513 .description = "Reset single port MIB counters",
514 .set = rtl8367_sw_reset_port_mibs,
515 }, {
516 .type = SWITCH_TYPE_STRING,
517 .name = "mib",
518 .description = "Get MIB counters for port",
519 //.max = 33,
520 .set = NULL,
521 .get = rtl8367_sw_get_port_mib,
522 },
523 };
524
525 static struct switch_attr rtl8367_vlan[] = {
526 {
527 .type = SWITCH_TYPE_STRING,
528 .name = "info",
529 .description = "Get vlan information",
530 .max = 1,
531 .set = NULL,
532 .get = rtl8367_sw_get_vlan_info,
533 },
534 };
535
536 static const struct switch_dev_ops rtl8367_sw_ops = {
537 .attr_global = {
538 .attr = rtl8367_globals,
539 .n_attr = ARRAY_SIZE(rtl8367_globals),
540 },
541 .attr_port = {
542 .attr = rtl8367_port,
543 .n_attr = ARRAY_SIZE(rtl8367_port),
544 },
545 .attr_vlan = {
546 .attr = rtl8367_vlan,
547 .n_attr = ARRAY_SIZE(rtl8367_vlan),
548 },
549
550 .get_vlan_ports = rtl8367_sw_get_vlan_ports,
551 .set_vlan_ports = rtl8367_sw_set_vlan_ports,
552 .get_port_pvid = rtl8367_sw_get_port_pvid,
553 .set_port_pvid = rtl8367_sw_set_port_pvid,
554 .reset_switch = rtl8367_sw_reset_switch,
555 .get_port_link = rtl8367_sw_get_port_link,
556 };
557
558 int rtl8367s_swconfig_init(void (*reset_func)(void))
559 {
560 struct rtl8367_priv *priv = &rtl8367_priv_data;
561 struct switch_dev *dev=&priv->swdev;
562 int err=0;
563
564 rtl8367_switch_reset_func = reset_func ;
565
566 memset(priv, 0, sizeof(struct rtl8367_priv));
567 priv->global_vlan_enable =0;
568
569 dev->name = "RTL8367C";
570 dev->cpu_port = RTL8367C_SW_CPU_PORT;
571 dev->ports = RTL8367C_NUM_PORTS;
572 dev->vlans = RTL8367C_NUM_VIDS;
573 dev->ops = &rtl8367_sw_ops;
574 dev->alias = "RTL8367C";
575 err = register_switch(dev, NULL);
576
577 pr_info("[%s]\n",__func__);
578
579 return err;
580 }