2 * Marvell 88E6xxx VLAN [Spanning Tree] Translation Unit (VTU [STU]) support
4 * Copyright (c) 2008 Marvell Semiconductor
5 * Copyright (c) 2015 CMC Electronics, Inc.
6 * Copyright (c) 2017 Savoir-faire Linux, Inc.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
14 #include <linux/interrupt.h>
15 #include <linux/irqdomain.h>
20 /* Offset 0x02: VTU FID Register */
22 static int mv88e6xxx_g1_vtu_fid_read(struct mv88e6xxx_chip
*chip
,
23 struct mv88e6xxx_vtu_entry
*entry
)
28 err
= mv88e6xxx_g1_read(chip
, MV88E6352_G1_VTU_FID
, &val
);
32 entry
->fid
= val
& MV88E6352_G1_VTU_FID_MASK
;
37 static int mv88e6xxx_g1_vtu_fid_write(struct mv88e6xxx_chip
*chip
,
38 struct mv88e6xxx_vtu_entry
*entry
)
40 u16 val
= entry
->fid
& MV88E6352_G1_VTU_FID_MASK
;
42 return mv88e6xxx_g1_write(chip
, MV88E6352_G1_VTU_FID
, val
);
45 /* Offset 0x03: VTU SID Register */
47 static int mv88e6xxx_g1_vtu_sid_read(struct mv88e6xxx_chip
*chip
,
48 struct mv88e6xxx_vtu_entry
*entry
)
53 err
= mv88e6xxx_g1_read(chip
, MV88E6352_G1_VTU_SID
, &val
);
57 entry
->sid
= val
& MV88E6352_G1_VTU_SID_MASK
;
62 static int mv88e6xxx_g1_vtu_sid_write(struct mv88e6xxx_chip
*chip
,
63 struct mv88e6xxx_vtu_entry
*entry
)
65 u16 val
= entry
->sid
& MV88E6352_G1_VTU_SID_MASK
;
67 return mv88e6xxx_g1_write(chip
, MV88E6352_G1_VTU_SID
, val
);
70 /* Offset 0x05: VTU Operation Register */
72 static int mv88e6xxx_g1_vtu_op_wait(struct mv88e6xxx_chip
*chip
)
74 return mv88e6xxx_g1_wait(chip
, MV88E6XXX_G1_VTU_OP
,
75 MV88E6XXX_G1_VTU_OP_BUSY
);
78 static int mv88e6xxx_g1_vtu_op(struct mv88e6xxx_chip
*chip
, u16 op
)
82 err
= mv88e6xxx_g1_write(chip
, MV88E6XXX_G1_VTU_OP
,
83 MV88E6XXX_G1_VTU_OP_BUSY
| op
);
87 return mv88e6xxx_g1_vtu_op_wait(chip
);
90 /* Offset 0x06: VTU VID Register */
92 static int mv88e6xxx_g1_vtu_vid_read(struct mv88e6xxx_chip
*chip
,
93 struct mv88e6xxx_vtu_entry
*entry
)
98 err
= mv88e6xxx_g1_read(chip
, MV88E6XXX_G1_VTU_VID
, &val
);
102 entry
->vid
= val
& 0xfff;
104 if (val
& MV88E6390_G1_VTU_VID_PAGE
)
105 entry
->vid
|= 0x1000;
107 entry
->valid
= !!(val
& MV88E6XXX_G1_VTU_VID_VALID
);
112 static int mv88e6xxx_g1_vtu_vid_write(struct mv88e6xxx_chip
*chip
,
113 struct mv88e6xxx_vtu_entry
*entry
)
115 u16 val
= entry
->vid
& 0xfff;
117 if (entry
->vid
& 0x1000)
118 val
|= MV88E6390_G1_VTU_VID_PAGE
;
121 val
|= MV88E6XXX_G1_VTU_VID_VALID
;
123 return mv88e6xxx_g1_write(chip
, MV88E6XXX_G1_VTU_VID
, val
);
126 /* Offset 0x07: VTU/STU Data Register 1
127 * Offset 0x08: VTU/STU Data Register 2
128 * Offset 0x09: VTU/STU Data Register 3
131 static int mv88e6185_g1_vtu_data_read(struct mv88e6xxx_chip
*chip
,
132 struct mv88e6xxx_vtu_entry
*entry
)
137 /* Read all 3 VTU/STU Data registers */
138 for (i
= 0; i
< 3; ++i
) {
142 err
= mv88e6xxx_g1_read(chip
, MV88E6XXX_G1_VTU_DATA1
+ i
, reg
);
147 /* Extract MemberTag and PortState data */
148 for (i
= 0; i
< mv88e6xxx_num_ports(chip
); ++i
) {
149 unsigned int member_offset
= (i
% 4) * 4;
150 unsigned int state_offset
= member_offset
+ 2;
152 entry
->member
[i
] = (regs
[i
/ 4] >> member_offset
) & 0x3;
153 entry
->state
[i
] = (regs
[i
/ 4] >> state_offset
) & 0x3;
159 static int mv88e6185_g1_vtu_data_write(struct mv88e6xxx_chip
*chip
,
160 struct mv88e6xxx_vtu_entry
*entry
)
165 /* Insert MemberTag and PortState data */
166 for (i
= 0; i
< mv88e6xxx_num_ports(chip
); ++i
) {
167 unsigned int member_offset
= (i
% 4) * 4;
168 unsigned int state_offset
= member_offset
+ 2;
170 regs
[i
/ 4] |= (entry
->member
[i
] & 0x3) << member_offset
;
171 regs
[i
/ 4] |= (entry
->state
[i
] & 0x3) << state_offset
;
174 /* Write all 3 VTU/STU Data registers */
175 for (i
= 0; i
< 3; ++i
) {
179 err
= mv88e6xxx_g1_write(chip
, MV88E6XXX_G1_VTU_DATA1
+ i
, reg
);
187 static int mv88e6390_g1_vtu_data_read(struct mv88e6xxx_chip
*chip
, u8
*data
)
192 /* Read the 2 VTU/STU Data registers */
193 for (i
= 0; i
< 2; ++i
) {
197 err
= mv88e6xxx_g1_read(chip
, MV88E6XXX_G1_VTU_DATA1
+ i
, reg
);
203 for (i
= 0; i
< mv88e6xxx_num_ports(chip
); ++i
) {
204 unsigned int offset
= (i
% 8) * 2;
206 data
[i
] = (regs
[i
/ 8] >> offset
) & 0x3;
212 static int mv88e6390_g1_vtu_data_write(struct mv88e6xxx_chip
*chip
, u8
*data
)
218 for (i
= 0; i
< mv88e6xxx_num_ports(chip
); ++i
) {
219 unsigned int offset
= (i
% 8) * 2;
221 regs
[i
/ 8] |= (data
[i
] & 0x3) << offset
;
224 /* Write the 2 VTU/STU Data registers */
225 for (i
= 0; i
< 2; ++i
) {
229 err
= mv88e6xxx_g1_write(chip
, MV88E6XXX_G1_VTU_DATA1
+ i
, reg
);
237 /* VLAN Translation Unit Operations */
239 static int mv88e6xxx_g1_vtu_stu_getnext(struct mv88e6xxx_chip
*chip
,
240 struct mv88e6xxx_vtu_entry
*entry
)
244 err
= mv88e6xxx_g1_vtu_sid_write(chip
, entry
);
248 err
= mv88e6xxx_g1_vtu_op(chip
, MV88E6XXX_G1_VTU_OP_STU_GET_NEXT
);
252 err
= mv88e6xxx_g1_vtu_sid_read(chip
, entry
);
256 return mv88e6xxx_g1_vtu_vid_read(chip
, entry
);
259 static int mv88e6xxx_g1_vtu_stu_get(struct mv88e6xxx_chip
*chip
,
260 struct mv88e6xxx_vtu_entry
*vtu
)
262 struct mv88e6xxx_vtu_entry stu
;
265 err
= mv88e6xxx_g1_vtu_sid_read(chip
, vtu
);
269 stu
.sid
= vtu
->sid
- 1;
271 err
= mv88e6xxx_g1_vtu_stu_getnext(chip
, &stu
);
275 if (stu
.sid
!= vtu
->sid
|| !stu
.valid
)
281 static int mv88e6xxx_g1_vtu_getnext(struct mv88e6xxx_chip
*chip
,
282 struct mv88e6xxx_vtu_entry
*entry
)
286 err
= mv88e6xxx_g1_vtu_op_wait(chip
);
290 /* To get the next higher active VID, the VTU GetNext operation can be
291 * started again without setting the VID registers since it already
292 * contains the last VID.
294 * To save a few hardware accesses and abstract this to the caller,
295 * write the VID only once, when the entry is given as invalid.
298 err
= mv88e6xxx_g1_vtu_vid_write(chip
, entry
);
303 err
= mv88e6xxx_g1_vtu_op(chip
, MV88E6XXX_G1_VTU_OP_VTU_GET_NEXT
);
307 return mv88e6xxx_g1_vtu_vid_read(chip
, entry
);
310 int mv88e6185_g1_vtu_getnext(struct mv88e6xxx_chip
*chip
,
311 struct mv88e6xxx_vtu_entry
*entry
)
316 err
= mv88e6xxx_g1_vtu_getnext(chip
, entry
);
321 err
= mv88e6185_g1_vtu_data_read(chip
, entry
);
325 /* VTU DBNum[3:0] are located in VTU Operation 3:0
326 * VTU DBNum[7:4] are located in VTU Operation 11:8
328 err
= mv88e6xxx_g1_read(chip
, MV88E6XXX_G1_VTU_OP
, &val
);
332 entry
->fid
= val
& 0x000f;
333 entry
->fid
|= (val
& 0x0f00) >> 4;
339 int mv88e6352_g1_vtu_getnext(struct mv88e6xxx_chip
*chip
,
340 struct mv88e6xxx_vtu_entry
*entry
)
344 /* Fetch VLAN MemberTag data from the VTU */
345 err
= mv88e6xxx_g1_vtu_getnext(chip
, entry
);
350 /* Fetch (and mask) VLAN PortState data from the STU */
351 err
= mv88e6xxx_g1_vtu_stu_get(chip
, entry
);
355 err
= mv88e6185_g1_vtu_data_read(chip
, entry
);
359 err
= mv88e6xxx_g1_vtu_fid_read(chip
, entry
);
367 int mv88e6390_g1_vtu_getnext(struct mv88e6xxx_chip
*chip
,
368 struct mv88e6xxx_vtu_entry
*entry
)
372 /* Fetch VLAN MemberTag data from the VTU */
373 err
= mv88e6xxx_g1_vtu_getnext(chip
, entry
);
378 err
= mv88e6390_g1_vtu_data_read(chip
, entry
->member
);
382 /* Fetch VLAN PortState data from the STU */
383 err
= mv88e6xxx_g1_vtu_stu_get(chip
, entry
);
387 err
= mv88e6390_g1_vtu_data_read(chip
, entry
->state
);
391 err
= mv88e6xxx_g1_vtu_fid_read(chip
, entry
);
399 int mv88e6185_g1_vtu_loadpurge(struct mv88e6xxx_chip
*chip
,
400 struct mv88e6xxx_vtu_entry
*entry
)
402 u16 op
= MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE
;
405 err
= mv88e6xxx_g1_vtu_op_wait(chip
);
409 err
= mv88e6xxx_g1_vtu_vid_write(chip
, entry
);
414 err
= mv88e6185_g1_vtu_data_write(chip
, entry
);
418 /* VTU DBNum[3:0] are located in VTU Operation 3:0
419 * VTU DBNum[7:4] are located in VTU Operation 11:8
421 op
|= entry
->fid
& 0x000f;
422 op
|= (entry
->fid
& 0x00f0) << 4;
425 return mv88e6xxx_g1_vtu_op(chip
, op
);
428 int mv88e6352_g1_vtu_loadpurge(struct mv88e6xxx_chip
*chip
,
429 struct mv88e6xxx_vtu_entry
*entry
)
433 err
= mv88e6xxx_g1_vtu_op_wait(chip
);
437 err
= mv88e6xxx_g1_vtu_vid_write(chip
, entry
);
442 /* Write MemberTag and PortState data */
443 err
= mv88e6185_g1_vtu_data_write(chip
, entry
);
447 err
= mv88e6xxx_g1_vtu_sid_write(chip
, entry
);
452 err
= mv88e6xxx_g1_vtu_op(chip
,
453 MV88E6XXX_G1_VTU_OP_STU_LOAD_PURGE
);
457 err
= mv88e6xxx_g1_vtu_fid_write(chip
, entry
);
462 /* Load/Purge VTU entry */
463 return mv88e6xxx_g1_vtu_op(chip
, MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE
);
466 int mv88e6390_g1_vtu_loadpurge(struct mv88e6xxx_chip
*chip
,
467 struct mv88e6xxx_vtu_entry
*entry
)
471 err
= mv88e6xxx_g1_vtu_op_wait(chip
);
475 err
= mv88e6xxx_g1_vtu_vid_write(chip
, entry
);
480 /* Write PortState data */
481 err
= mv88e6390_g1_vtu_data_write(chip
, entry
->state
);
485 err
= mv88e6xxx_g1_vtu_sid_write(chip
, entry
);
490 err
= mv88e6xxx_g1_vtu_op(chip
,
491 MV88E6XXX_G1_VTU_OP_STU_LOAD_PURGE
);
495 /* Write MemberTag data */
496 err
= mv88e6390_g1_vtu_data_write(chip
, entry
->member
);
500 err
= mv88e6xxx_g1_vtu_fid_write(chip
, entry
);
505 /* Load/Purge VTU entry */
506 return mv88e6xxx_g1_vtu_op(chip
, MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE
);
509 int mv88e6xxx_g1_vtu_flush(struct mv88e6xxx_chip
*chip
)
513 err
= mv88e6xxx_g1_vtu_op_wait(chip
);
517 return mv88e6xxx_g1_vtu_op(chip
, MV88E6XXX_G1_VTU_OP_FLUSH_ALL
);
520 static irqreturn_t
mv88e6xxx_g1_vtu_prob_irq_thread_fn(int irq
, void *dev_id
)
522 struct mv88e6xxx_chip
*chip
= dev_id
;
523 struct mv88e6xxx_vtu_entry entry
;
528 mutex_lock(&chip
->reg_lock
);
530 err
= mv88e6xxx_g1_vtu_op(chip
, MV88E6XXX_G1_VTU_OP_GET_CLR_VIOLATION
);
534 err
= mv88e6xxx_g1_read(chip
, MV88E6XXX_G1_VTU_OP
, &val
);
538 err
= mv88e6xxx_g1_vtu_vid_read(chip
, &entry
);
542 spid
= val
& MV88E6XXX_G1_VTU_OP_SPID_MASK
;
544 if (val
& MV88E6XXX_G1_VTU_OP_MEMBER_VIOLATION
) {
545 dev_err_ratelimited(chip
->dev
, "VTU member violation for vid %d, source port %d\n",
547 chip
->ports
[spid
].vtu_member_violation
++;
550 if (val
& MV88E6XXX_G1_VTU_OP_MISS_VIOLATION
) {
551 dev_dbg_ratelimited(chip
->dev
, "VTU miss violation for vid %d, source port %d\n",
553 chip
->ports
[spid
].vtu_miss_violation
++;
556 mutex_unlock(&chip
->reg_lock
);
561 mutex_unlock(&chip
->reg_lock
);
563 dev_err(chip
->dev
, "VTU problem: error %d while handling interrupt\n",
569 int mv88e6xxx_g1_vtu_prob_irq_setup(struct mv88e6xxx_chip
*chip
)
573 chip
->vtu_prob_irq
= irq_find_mapping(chip
->g1_irq
.domain
,
574 MV88E6XXX_G1_STS_IRQ_VTU_PROB
);
575 if (chip
->vtu_prob_irq
< 0)
576 return chip
->vtu_prob_irq
;
578 err
= request_threaded_irq(chip
->vtu_prob_irq
, NULL
,
579 mv88e6xxx_g1_vtu_prob_irq_thread_fn
,
580 IRQF_ONESHOT
, "mv88e6xxx-g1-vtu-prob",
583 irq_dispose_mapping(chip
->vtu_prob_irq
);
588 void mv88e6xxx_g1_vtu_prob_irq_free(struct mv88e6xxx_chip
*chip
)
590 free_irq(chip
->vtu_prob_irq
, chip
);
591 irq_dispose_mapping(chip
->vtu_prob_irq
);