mvsw61xx: clean up and expand register definitions
[openwrt/openwrt.git] / target / linux / generic / files / drivers / net / phy / mvsw61xx.c
1 /*
2 * Marvell 88E61xx switch driver
3 *
4 * Copyright (c) 2014 Claudio Leite <leitec@staticky.com>
5 *
6 * Based on code (c) 2008 Felix Fietkau <nbd@openwrt.org>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License v2 as published by the
10 * Free Software Foundation
11 */
12
13 #include <linux/kernel.h>
14 #include <linux/module.h>
15 #include <linux/init.h>
16 #include <linux/list.h>
17 #include <linux/mii.h>
18 #include <linux/phy.h>
19 #include <linux/of.h>
20 #include <linux/of_mdio.h>
21 #include <linux/delay.h>
22 #include <linux/switch.h>
23 #include <linux/device.h>
24 #include <linux/platform_device.h>
25
26 #include "mvsw61xx.h"
27
28 MODULE_DESCRIPTION("Marvell 88E61xx Switch driver");
29 MODULE_AUTHOR("Claudio Leite <leitec@staticky.com>");
30 MODULE_LICENSE("GPL v2");
31 MODULE_ALIAS("platform:mvsw61xx");
32
33 /*
34 * Register access is done through direct or indirect addressing,
35 * depending on how the switch is physically connected.
36 *
37 * Direct addressing: all port and global registers directly
38 * accessible via an address/register pair
39 *
40 * Indirect addressing: switch is mapped at a single address,
41 * port and global registers accessible via a single command/data
42 * register pair
43 */
44
45 static int
46 mvsw61xx_wait_mask_raw(struct mii_bus *bus, int addr,
47 int reg, u16 mask, u16 val)
48 {
49 int i = 100;
50 u16 r;
51
52 do {
53 r = bus->read(bus, addr, reg);
54 if ((r & mask) == val)
55 return 0;
56 } while (--i > 0);
57
58 return -ETIMEDOUT;
59 }
60
61 static u16
62 r16(struct mii_bus *bus, bool indirect, int base_addr, int addr, int reg)
63 {
64 u16 ind_addr;
65
66 if (!indirect)
67 return bus->read(bus, addr, reg);
68
69 /* Indirect read: First, make sure switch is free */
70 mvsw61xx_wait_mask_raw(bus, base_addr, MV_INDIRECT_REG_CMD,
71 MV_INDIRECT_INPROGRESS, 0);
72
73 /* Load address and request read */
74 ind_addr = MV_INDIRECT_READ | (addr << MV_INDIRECT_ADDR_S) | reg;
75 bus->write(bus, base_addr, MV_INDIRECT_REG_CMD,
76 ind_addr);
77
78 /* Wait until it's ready */
79 mvsw61xx_wait_mask_raw(bus, base_addr, MV_INDIRECT_REG_CMD,
80 MV_INDIRECT_INPROGRESS, 0);
81
82 /* Read the requested data */
83 return bus->read(bus, base_addr, MV_INDIRECT_REG_DATA);
84 }
85
86 static void
87 w16(struct mii_bus *bus, bool indirect, int base_addr, int addr,
88 int reg, u16 val)
89 {
90 u16 ind_addr;
91
92 if (!indirect) {
93 bus->write(bus, addr, reg, val);
94 return;
95 }
96
97 /* Indirect write: First, make sure switch is free */
98 mvsw61xx_wait_mask_raw(bus, base_addr, MV_INDIRECT_REG_CMD,
99 MV_INDIRECT_INPROGRESS, 0);
100
101 /* Load the data to be written */
102 bus->write(bus, base_addr, MV_INDIRECT_REG_DATA, val);
103
104 /* Wait again for switch to be free */
105 mvsw61xx_wait_mask_raw(bus, base_addr, MV_INDIRECT_REG_CMD,
106 MV_INDIRECT_INPROGRESS, 0);
107
108 /* Load address, and issue write command */
109 ind_addr = MV_INDIRECT_WRITE | (addr << MV_INDIRECT_ADDR_S) | reg;
110 bus->write(bus, base_addr, MV_INDIRECT_REG_CMD,
111 ind_addr);
112 }
113
114 /* swconfig support */
115
116 static inline u16
117 sr16(struct switch_dev *dev, int addr, int reg)
118 {
119 struct mvsw61xx_state *state = get_state(dev);
120
121 return r16(state->bus, state->is_indirect, state->base_addr, addr, reg);
122 }
123
124 static inline void
125 sw16(struct switch_dev *dev, int addr, int reg, u16 val)
126 {
127 struct mvsw61xx_state *state = get_state(dev);
128
129 w16(state->bus, state->is_indirect, state->base_addr, addr, reg, val);
130 }
131
132 static int
133 mvsw61xx_wait_mask_s(struct switch_dev *dev, int addr,
134 int reg, u16 mask, u16 val)
135 {
136 int i = 100;
137 u16 r;
138
139 do {
140 r = sr16(dev, addr, reg) & mask;
141 if (r == val)
142 return 0;
143 } while (--i > 0);
144
145 return -ETIMEDOUT;
146 }
147
148 static int
149 mvsw61xx_get_port_mask(struct switch_dev *dev,
150 const struct switch_attr *attr, struct switch_val *val)
151 {
152 struct mvsw61xx_state *state = get_state(dev);
153 char *buf = state->buf;
154 int port, len, i;
155 u16 reg;
156
157 port = val->port_vlan;
158 reg = sr16(dev, MV_PORTREG(VLANMAP, port)) & MV_PORTS_MASK;
159
160 len = sprintf(buf, "0x%04x: ", reg);
161
162 for (i = 0; i < MV_PORTS; i++) {
163 if (reg & (1 << i))
164 len += sprintf(buf + len, "%d ", i);
165 else if (i == port)
166 len += sprintf(buf + len, "(%d) ", i);
167 }
168
169 val->value.s = buf;
170
171 return 0;
172 }
173
174 static int
175 mvsw61xx_get_port_qmode(struct switch_dev *dev,
176 const struct switch_attr *attr, struct switch_val *val)
177 {
178 struct mvsw61xx_state *state = get_state(dev);
179
180 val->value.i = state->ports[val->port_vlan].qmode;
181
182 return 0;
183 }
184
185 static int
186 mvsw61xx_set_port_qmode(struct switch_dev *dev,
187 const struct switch_attr *attr, struct switch_val *val)
188 {
189 struct mvsw61xx_state *state = get_state(dev);
190
191 state->ports[val->port_vlan].qmode = val->value.i;
192
193 return 0;
194 }
195
196 static int
197 mvsw61xx_get_pvid(struct switch_dev *dev, int port, int *val)
198 {
199 struct mvsw61xx_state *state = get_state(dev);
200
201 *val = state->ports[port].pvid;
202
203 return 0;
204 }
205
206 static int
207 mvsw61xx_set_pvid(struct switch_dev *dev, int port, int val)
208 {
209 struct mvsw61xx_state *state = get_state(dev);
210
211 if (val < 0 || val >= MV_VLANS)
212 return -EINVAL;
213
214 state->ports[port].pvid = (u16)val;
215
216 return 0;
217 }
218
219 static int
220 mvsw61xx_get_port_status(struct switch_dev *dev,
221 const struct switch_attr *attr, struct switch_val *val)
222 {
223 struct mvsw61xx_state *state = get_state(dev);
224 char *buf = state->buf;
225 u16 status, speed;
226 int len;
227
228 status = sr16(dev, MV_PORTREG(STATUS, val->port_vlan));
229 speed = (status & MV_PORT_STATUS_SPEED_MASK) >>
230 MV_PORT_STATUS_SPEED_SHIFT;
231
232 len = sprintf(buf, "link: ");
233 if (status & MV_PORT_STATUS_LINK) {
234 len += sprintf(buf + len, "up, speed: ");
235
236 switch (speed) {
237 case MV_PORT_STATUS_SPEED_10:
238 len += sprintf(buf + len, "10");
239 break;
240 case MV_PORT_STATUS_SPEED_100:
241 len += sprintf(buf + len, "100");
242 break;
243 case MV_PORT_STATUS_SPEED_1000:
244 len += sprintf(buf + len, "1000");
245 break;
246 }
247
248 len += sprintf(buf + len, " Mbps, duplex: ");
249
250 if (status & MV_PORT_STATUS_FDX)
251 len += sprintf(buf + len, "full");
252 else
253 len += sprintf(buf + len, "half");
254 } else {
255 len += sprintf(buf + len, "down");
256 }
257
258 val->value.s = buf;
259
260 return 0;
261 }
262
263 static int
264 mvsw61xx_get_port_speed(struct switch_dev *dev,
265 const struct switch_attr *attr, struct switch_val *val)
266 {
267 u16 status, speed;
268
269 status = sr16(dev, MV_PORTREG(STATUS, val->port_vlan));
270 speed = (status & MV_PORT_STATUS_SPEED_MASK) >>
271 MV_PORT_STATUS_SPEED_SHIFT;
272
273 val->value.i = 0;
274
275 if (status & MV_PORT_STATUS_LINK) {
276 switch (speed) {
277 case MV_PORT_STATUS_SPEED_10:
278 val->value.i = 10;
279 break;
280 case MV_PORT_STATUS_SPEED_100:
281 val->value.i = 100;
282 break;
283 case MV_PORT_STATUS_SPEED_1000:
284 val->value.i = 1000;
285 break;
286 }
287 }
288
289 return 0;
290 }
291
292 static int mvsw61xx_get_vlan_ports(struct switch_dev *dev,
293 struct switch_val *val)
294 {
295 struct mvsw61xx_state *state = get_state(dev);
296 int i, j, mode, vno;
297
298 vno = val->port_vlan;
299
300 if (vno <= 0 || vno >= dev->vlans)
301 return -EINVAL;
302
303 for (i = 0, j = 0; i < dev->ports; i++) {
304 if (state->vlans[vno].mask & (1 << i)) {
305 val->value.ports[j].id = i;
306
307 mode = (state->vlans[vno].port_mode >> (i * 4)) & 0xf;
308 if (mode == MV_VTUCTL_EGRESS_TAGGED)
309 val->value.ports[j].flags =
310 (1 << SWITCH_PORT_FLAG_TAGGED);
311 else
312 val->value.ports[j].flags = 0;
313
314 j++;
315 }
316 }
317
318 val->len = j;
319
320 return 0;
321 }
322
323 static int mvsw61xx_set_vlan_ports(struct switch_dev *dev,
324 struct switch_val *val)
325 {
326 struct mvsw61xx_state *state = get_state(dev);
327 int i, mode, pno, vno;
328
329 vno = val->port_vlan;
330
331 if (vno <= 0 || vno >= dev->vlans)
332 return -EINVAL;
333
334 state->vlans[vno].mask = 0;
335 state->vlans[vno].port_mode = 0;
336
337 if(state->vlans[vno].vid == 0)
338 state->vlans[vno].vid = vno;
339
340 for (i = 0; i < val->len; i++) {
341 pno = val->value.ports[i].id;
342
343 state->vlans[vno].mask |= (1 << pno);
344 if (val->value.ports[i].flags &
345 (1 << SWITCH_PORT_FLAG_TAGGED))
346 mode = MV_VTUCTL_EGRESS_TAGGED;
347 else
348 mode = MV_VTUCTL_EGRESS_UNTAGGED;
349
350 state->vlans[vno].port_mode |= mode << (pno * 4);
351 }
352
353 /*
354 * DISCARD is nonzero, so it must be explicitly
355 * set on ports not in the VLAN.
356 */
357 for (i = 0; i < dev->ports; i++)
358 if (!(state->vlans[vno].mask & (1 << i)))
359 state->vlans[vno].port_mode |=
360 MV_VTUCTL_DISCARD << (i * 4);
361
362 return 0;
363 }
364
365 static int mvsw61xx_get_vlan_port_based(struct switch_dev *dev,
366 const struct switch_attr *attr, struct switch_val *val)
367 {
368 struct mvsw61xx_state *state = get_state(dev);
369 int vno = val->port_vlan;
370
371 if (vno <= 0 || vno >= dev->vlans)
372 return -EINVAL;
373
374 if (state->vlans[vno].port_based)
375 val->value.i = 1;
376 else
377 val->value.i = 0;
378
379 return 0;
380 }
381
382 static int mvsw61xx_set_vlan_port_based(struct switch_dev *dev,
383 const struct switch_attr *attr, struct switch_val *val)
384 {
385 struct mvsw61xx_state *state = get_state(dev);
386 int vno = val->port_vlan;
387
388 if (vno <= 0 || vno >= dev->vlans)
389 return -EINVAL;
390
391 if (val->value.i == 1)
392 state->vlans[vno].port_based = true;
393 else
394 state->vlans[vno].port_based = false;
395
396 return 0;
397 }
398
399 static int mvsw61xx_get_vid(struct switch_dev *dev,
400 const struct switch_attr *attr, struct switch_val *val)
401 {
402 struct mvsw61xx_state *state = get_state(dev);
403 int vno = val->port_vlan;
404
405 if (vno <= 0 || vno >= dev->vlans)
406 return -EINVAL;
407
408 val->value.i = state->vlans[vno].vid;
409
410 return 0;
411 }
412
413 static int mvsw61xx_set_vid(struct switch_dev *dev,
414 const struct switch_attr *attr, struct switch_val *val)
415 {
416 struct mvsw61xx_state *state = get_state(dev);
417 int vno = val->port_vlan;
418
419 if (vno <= 0 || vno >= dev->vlans)
420 return -EINVAL;
421
422 state->vlans[vno].vid = val->value.i;
423
424 return 0;
425 }
426
427 static int mvsw61xx_get_enable_vlan(struct switch_dev *dev,
428 const struct switch_attr *attr, struct switch_val *val)
429 {
430 struct mvsw61xx_state *state = get_state(dev);
431
432 val->value.i = state->vlan_enabled;
433
434 return 0;
435 }
436
437 static int mvsw61xx_set_enable_vlan(struct switch_dev *dev,
438 const struct switch_attr *attr, struct switch_val *val)
439 {
440 struct mvsw61xx_state *state = get_state(dev);
441
442 state->vlan_enabled = val->value.i;
443
444 return 0;
445 }
446
447 static int mvsw61xx_vtu_program(struct switch_dev *dev)
448 {
449 struct mvsw61xx_state *state = get_state(dev);
450 u16 v1, v2;
451 int i;
452
453 /* Flush */
454 mvsw61xx_wait_mask_s(dev, MV_GLOBALREG(VTU_OP),
455 MV_VTUOP_INPROGRESS, 0);
456 sw16(dev, MV_GLOBALREG(VTU_OP),
457 MV_VTUOP_INPROGRESS | MV_VTUOP_PURGE);
458
459 /* Write VLAN table */
460 for (i = 1; i < dev->vlans; i++) {
461 if (state->vlans[i].mask == 0 ||
462 state->vlans[i].vid == 0 ||
463 state->vlans[i].port_based == true)
464 continue;
465
466 mvsw61xx_wait_mask_s(dev, MV_GLOBALREG(VTU_OP),
467 MV_VTUOP_INPROGRESS, 0);
468
469 sw16(dev, MV_GLOBALREG(VTU_VID),
470 MV_VTU_VID_VALID | state->vlans[i].vid);
471
472 v1 = (u16)(state->vlans[i].port_mode & 0xffff);
473 v2 = (u16)((state->vlans[i].port_mode >> 16) & 0xffff);
474
475 sw16(dev, MV_GLOBALREG(VTU_DATA1), v1);
476 sw16(dev, MV_GLOBALREG(VTU_DATA2), v2);
477
478 sw16(dev, MV_GLOBALREG(VTU_OP),
479 MV_VTUOP_INPROGRESS | MV_VTUOP_LOAD);
480 mvsw61xx_wait_mask_s(dev, MV_GLOBALREG(VTU_OP),
481 MV_VTUOP_INPROGRESS, 0);
482 }
483
484 return 0;
485 }
486
487 static void mvsw61xx_vlan_port_config(struct switch_dev *dev, int vno)
488 {
489 struct mvsw61xx_state *state = get_state(dev);
490 int i, mode;
491
492 for (i = 0; i < dev->ports; i++) {
493 if (!(state->vlans[vno].mask & (1 << i)))
494 continue;
495
496 mode = (state->vlans[vno].port_mode >> (i * 4)) & 0xf;
497
498 if(mode != MV_VTUCTL_EGRESS_TAGGED)
499 state->ports[i].pvid = state->vlans[vno].vid;
500
501 if (state->vlans[vno].port_based)
502 state->ports[i].mask |= state->vlans[vno].mask;
503 else
504 state->ports[i].qmode = MV_8021Q_MODE_SECURE;
505 }
506 }
507
508 static int mvsw61xx_update_state(struct switch_dev *dev)
509 {
510 struct mvsw61xx_state *state = get_state(dev);
511 int i;
512 u16 reg;
513
514 if (!state->registered)
515 return -EINVAL;
516
517 mvsw61xx_vtu_program(dev);
518
519 /*
520 * Set 802.1q-only mode if vlan_enabled is true.
521 *
522 * Without this, even if 802.1q is enabled for
523 * a port/VLAN, it still depends on the port-based
524 * VLAN mask being set.
525 *
526 * With this setting, port-based VLANs are still
527 * functional, provided the VID is not in the VTU.
528 */
529 reg = sr16(dev, MV_GLOBAL2REG(SDET_POLARITY));
530
531 if (state->vlan_enabled)
532 reg |= MV_8021Q_VLAN_ONLY;
533 else
534 reg &= ~MV_8021Q_VLAN_ONLY;
535
536 sw16(dev, MV_GLOBAL2REG(SDET_POLARITY), reg);
537
538 /*
539 * Set port-based VLAN masks on each port
540 * based only on VLAN definitions known to
541 * the driver (i.e. in state).
542 *
543 * This means any pre-existing port mapping is
544 * wiped out once our driver is initialized.
545 */
546 for (i = 0; i < dev->ports; i++) {
547 state->ports[i].mask = 0;
548 state->ports[i].qmode = MV_8021Q_MODE_DISABLE;
549 }
550
551 for (i = 0; i < dev->vlans; i++)
552 mvsw61xx_vlan_port_config(dev, i);
553
554 for (i = 0; i < dev->ports; i++) {
555 reg = sr16(dev, MV_PORTREG(VLANID, i)) & ~MV_PVID_MASK;
556 reg |= state->ports[i].pvid;
557 sw16(dev, MV_PORTREG(VLANID, i), reg);
558
559 state->ports[i].mask &= ~(1 << i);
560
561 reg = sr16(dev, MV_PORTREG(VLANMAP, i)) & ~MV_PORTS_MASK;
562 reg |= state->ports[i].mask;
563 sw16(dev, MV_PORTREG(VLANMAP, i), reg);
564
565 reg = sr16(dev, MV_PORTREG(CONTROL2, i)) &
566 ~MV_8021Q_MODE_MASK;
567 reg |= state->ports[i].qmode << MV_8021Q_MODE_SHIFT;
568 sw16(dev, MV_PORTREG(CONTROL2, i), reg);
569 }
570
571 return 0;
572 }
573
574 static int mvsw61xx_apply(struct switch_dev *dev)
575 {
576 return mvsw61xx_update_state(dev);
577 }
578
579 static int mvsw61xx_reset(struct switch_dev *dev)
580 {
581 struct mvsw61xx_state *state = get_state(dev);
582 int i;
583 u16 reg;
584
585 /* Disable all ports before reset */
586 for (i = 0; i < dev->ports; i++) {
587 reg = sr16(dev, MV_PORTREG(CONTROL, i)) &
588 ~MV_PORTCTRL_FORWARDING;
589 sw16(dev, MV_PORTREG(CONTROL, i), reg);
590 }
591
592 reg = sr16(dev, MV_GLOBALREG(CONTROL)) | MV_CONTROL_RESET;
593
594 sw16(dev, MV_GLOBALREG(CONTROL), reg);
595 if (mvsw61xx_wait_mask_s(dev, MV_GLOBALREG(CONTROL),
596 MV_CONTROL_RESET, 0) < 0)
597 return -ETIMEDOUT;
598
599 for (i = 0; i < dev->ports; i++) {
600 state->ports[i].qmode = 0;
601 state->ports[i].mask = 0;
602 state->ports[i].pvid = 0;
603
604 /* Force flow control off */
605 reg = sr16(dev, MV_PORTREG(PHYCTL, i)) & ~MV_PHYCTL_FC_MASK;
606 reg |= MV_PHYCTL_FC_DISABLE;
607 sw16(dev, MV_PORTREG(PHYCTL, i), reg);
608
609 /* Set port association vector */
610 sw16(dev, MV_PORTREG(ASSOC, i), (1 << i));
611 }
612
613 for (i = 0; i < dev->vlans; i++) {
614 state->vlans[i].port_based = false;
615 state->vlans[i].mask = 0;
616 state->vlans[i].vid = 0;
617 state->vlans[i].port_mode = 0;
618 }
619
620 state->vlan_enabled = 0;
621
622 mvsw61xx_update_state(dev);
623
624 /* Re-enable ports */
625 for (i = 0; i < dev->ports; i++) {
626 reg = sr16(dev, MV_PORTREG(CONTROL, i)) |
627 MV_PORTCTRL_FORWARDING;
628 sw16(dev, MV_PORTREG(CONTROL, i), reg);
629 }
630
631 return 0;
632 }
633
634 enum {
635 MVSW61XX_ENABLE_VLAN,
636 };
637
638 enum {
639 MVSW61XX_VLAN_PORT_BASED,
640 MVSW61XX_VLAN_ID,
641 };
642
643 enum {
644 MVSW61XX_PORT_MASK,
645 MVSW61XX_PORT_QMODE,
646 MVSW61XX_PORT_STATUS,
647 MVSW61XX_PORT_LINK,
648 };
649
650 static const struct switch_attr mvsw61xx_global[] = {
651 [MVSW61XX_ENABLE_VLAN] = {
652 .id = MVSW61XX_ENABLE_VLAN,
653 .type = SWITCH_TYPE_INT,
654 .name = "enable_vlan",
655 .description = "Enable 802.1q VLAN support",
656 .get = mvsw61xx_get_enable_vlan,
657 .set = mvsw61xx_set_enable_vlan,
658 },
659 };
660
661 static const struct switch_attr mvsw61xx_vlan[] = {
662 [MVSW61XX_VLAN_PORT_BASED] = {
663 .id = MVSW61XX_VLAN_PORT_BASED,
664 .type = SWITCH_TYPE_INT,
665 .name = "port_based",
666 .description = "Use port-based (non-802.1q) VLAN only",
667 .get = mvsw61xx_get_vlan_port_based,
668 .set = mvsw61xx_set_vlan_port_based,
669 },
670 [MVSW61XX_VLAN_ID] = {
671 .id = MVSW61XX_VLAN_ID,
672 .type = SWITCH_TYPE_INT,
673 .name = "vid",
674 .description = "Get/set VLAN ID",
675 .get = mvsw61xx_get_vid,
676 .set = mvsw61xx_set_vid,
677 },
678 };
679
680 static const struct switch_attr mvsw61xx_port[] = {
681 [MVSW61XX_PORT_MASK] = {
682 .id = MVSW61XX_PORT_MASK,
683 .type = SWITCH_TYPE_STRING,
684 .description = "Port-based VLAN mask",
685 .name = "mask",
686 .get = mvsw61xx_get_port_mask,
687 .set = NULL,
688 },
689 [MVSW61XX_PORT_QMODE] = {
690 .id = MVSW61XX_PORT_QMODE,
691 .type = SWITCH_TYPE_INT,
692 .description = "802.1q mode: 0=off/1=fallback/2=check/3=secure",
693 .name = "qmode",
694 .get = mvsw61xx_get_port_qmode,
695 .set = mvsw61xx_set_port_qmode,
696 },
697 [MVSW61XX_PORT_STATUS] = {
698 .id = MVSW61XX_PORT_STATUS,
699 .type = SWITCH_TYPE_STRING,
700 .description = "Return port status",
701 .name = "status",
702 .get = mvsw61xx_get_port_status,
703 .set = NULL,
704 },
705 [MVSW61XX_PORT_LINK] = {
706 .id = MVSW61XX_PORT_LINK,
707 .type = SWITCH_TYPE_INT,
708 .description = "Get link speed",
709 .name = "link",
710 .get = mvsw61xx_get_port_speed,
711 .set = NULL,
712 },
713 };
714
715 static const struct switch_dev_ops mvsw61xx_ops = {
716 .attr_global = {
717 .attr = mvsw61xx_global,
718 .n_attr = ARRAY_SIZE(mvsw61xx_global),
719 },
720 .attr_vlan = {
721 .attr = mvsw61xx_vlan,
722 .n_attr = ARRAY_SIZE(mvsw61xx_vlan),
723 },
724 .attr_port = {
725 .attr = mvsw61xx_port,
726 .n_attr = ARRAY_SIZE(mvsw61xx_port),
727 },
728 .get_port_pvid = mvsw61xx_get_pvid,
729 .set_port_pvid = mvsw61xx_set_pvid,
730 .get_vlan_ports = mvsw61xx_get_vlan_ports,
731 .set_vlan_ports = mvsw61xx_set_vlan_ports,
732 .apply_config = mvsw61xx_apply,
733 .reset_switch = mvsw61xx_reset,
734 };
735
736 /* end swconfig stuff */
737
738 static int mvsw61xx_probe(struct platform_device *pdev)
739 {
740 struct mvsw61xx_state *state;
741 struct device_node *np = pdev->dev.of_node;
742 struct device_node *mdio;
743 char *model_str;
744 u32 val;
745 int err;
746
747 state = kzalloc(sizeof(*state), GFP_KERNEL);
748 if (!state)
749 return -ENOMEM;
750
751 mdio = of_parse_phandle(np, "mii-bus", 0);
752 if (!mdio) {
753 dev_err(&pdev->dev, "Couldn't get MII bus handle\n");
754 err = -ENODEV;
755 goto out_err;
756 }
757
758 state->bus = of_mdio_find_bus(mdio);
759 if (!state->bus) {
760 dev_err(&pdev->dev, "Couldn't find MII bus from handle\n");
761 err = -ENODEV;
762 goto out_err;
763 }
764
765 state->is_indirect = of_property_read_bool(np, "is-indirect");
766
767 if (state->is_indirect) {
768 if (of_property_read_u32(np, "reg", &val)) {
769 dev_err(&pdev->dev, "Switch address not specified\n");
770 err = -ENODEV;
771 goto out_err;
772 }
773
774 state->base_addr = val;
775 } else {
776 state->base_addr = MV_BASE;
777 }
778
779 state->model = r16(state->bus, state->is_indirect, state->base_addr,
780 MV_PORTREG(IDENT, 0)) & MV_IDENT_MASK;
781
782 switch(state->model) {
783 case MV_IDENT_VALUE_6171:
784 model_str = MV_IDENT_STR_6171;
785 break;
786 case MV_IDENT_VALUE_6172:
787 model_str = MV_IDENT_STR_6172;
788 break;
789 case MV_IDENT_VALUE_6176:
790 model_str = MV_IDENT_STR_6176;
791 break;
792 default:
793 dev_err(&pdev->dev, "No compatible switch found at 0x%02x\n",
794 state->base_addr);
795 err = -ENODEV;
796 goto out_err;
797 }
798
799 platform_set_drvdata(pdev, state);
800 dev_info(&pdev->dev, "Found %s at %s:%02x\n", model_str,
801 state->bus->id, state->base_addr);
802
803 dev_info(&pdev->dev, "Using %sdirect addressing\n",
804 (state->is_indirect ? "in" : ""));
805
806 if (of_property_read_u32(np, "cpu-port-0", &val)) {
807 dev_err(&pdev->dev, "CPU port not set\n");
808 err = -ENODEV;
809 goto out_err;
810 }
811
812 state->cpu_port0 = val;
813
814 if (!of_property_read_u32(np, "cpu-port-1", &val))
815 state->cpu_port1 = val;
816 else
817 state->cpu_port1 = -1;
818
819 state->dev.vlans = MV_VLANS;
820 state->dev.cpu_port = state->cpu_port0;
821 state->dev.ports = MV_PORTS;
822 state->dev.name = model_str;
823 state->dev.ops = &mvsw61xx_ops;
824 state->dev.alias = dev_name(&pdev->dev);
825
826 err = register_switch(&state->dev, NULL);
827 if (err < 0)
828 goto out_err;
829
830 state->registered = true;
831
832 return 0;
833 out_err:
834 kfree(state);
835 return err;
836 }
837
838 static int
839 mvsw61xx_remove(struct platform_device *pdev)
840 {
841 struct mvsw61xx_state *state = platform_get_drvdata(pdev);
842
843 if (state->registered)
844 unregister_switch(&state->dev);
845
846 kfree(state);
847
848 return 0;
849 }
850
851 static const struct of_device_id mvsw61xx_match[] = {
852 { .compatible = "marvell,88e6171" },
853 { .compatible = "marvell,88e6172" },
854 { .compatible = "marvell,88e6176" },
855 { }
856 };
857 MODULE_DEVICE_TABLE(of, mvsw61xx_match);
858
859 static struct platform_driver mvsw61xx_driver = {
860 .probe = mvsw61xx_probe,
861 .remove = mvsw61xx_remove,
862 .driver = {
863 .name = "mvsw61xx",
864 .of_match_table = of_match_ptr(mvsw61xx_match),
865 .owner = THIS_MODULE,
866 },
867 };
868
869 static int __init mvsw61xx_module_init(void)
870 {
871 return platform_driver_register(&mvsw61xx_driver);
872 }
873 late_initcall(mvsw61xx_module_init);
874
875 static void __exit mvsw61xx_module_exit(void)
876 {
877 platform_driver_unregister(&mvsw61xx_driver);
878 }
879 module_exit(mvsw61xx_module_exit);