1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Marvell 88E6xxx Address Translation Unit (ATU) support
5 * Copyright (c) 2008 Marvell Semiconductor
6 * Copyright (c) 2017 Savoir-faire Linux, Inc.
9 #include <linux/bitfield.h>
10 #include <linux/interrupt.h>
11 #include <linux/irqdomain.h>
15 #include "switchdev.h"
18 /* Offset 0x01: ATU FID Register */
20 static int mv88e6xxx_g1_atu_fid_write(struct mv88e6xxx_chip
*chip
, u16 fid
)
22 return mv88e6xxx_g1_write(chip
, MV88E6352_G1_ATU_FID
, fid
& 0xfff);
25 /* Offset 0x0A: ATU Control Register */
27 int mv88e6xxx_g1_atu_set_learn2all(struct mv88e6xxx_chip
*chip
, bool learn2all
)
32 err
= mv88e6xxx_g1_read(chip
, MV88E6XXX_G1_ATU_CTL
, &val
);
37 val
|= MV88E6XXX_G1_ATU_CTL_LEARN2ALL
;
39 val
&= ~MV88E6XXX_G1_ATU_CTL_LEARN2ALL
;
41 return mv88e6xxx_g1_write(chip
, MV88E6XXX_G1_ATU_CTL
, val
);
44 int mv88e6xxx_g1_atu_set_age_time(struct mv88e6xxx_chip
*chip
,
47 const unsigned int coeff
= chip
->info
->age_time_coeff
;
48 const unsigned int min
= 0x01 * coeff
;
49 const unsigned int max
= 0xff * coeff
;
54 if (msecs
< min
|| msecs
> max
)
57 /* Round to nearest multiple of coeff */
58 age_time
= (msecs
+ coeff
/ 2) / coeff
;
60 err
= mv88e6xxx_g1_read(chip
, MV88E6XXX_G1_ATU_CTL
, &val
);
64 /* AgeTime is 11:4 bits */
68 err
= mv88e6xxx_g1_write(chip
, MV88E6XXX_G1_ATU_CTL
, val
);
72 dev_dbg(chip
->dev
, "AgeTime set to 0x%02x (%d ms)\n", age_time
,
78 int mv88e6165_g1_atu_get_hash(struct mv88e6xxx_chip
*chip
, u8
*hash
)
83 err
= mv88e6xxx_g1_read(chip
, MV88E6XXX_G1_ATU_CTL
, &val
);
87 *hash
= val
& MV88E6161_G1_ATU_CTL_HASH_MASK
;
92 int mv88e6165_g1_atu_set_hash(struct mv88e6xxx_chip
*chip
, u8 hash
)
97 if (hash
& ~MV88E6161_G1_ATU_CTL_HASH_MASK
)
100 err
= mv88e6xxx_g1_read(chip
, MV88E6XXX_G1_ATU_CTL
, &val
);
104 val
&= ~MV88E6161_G1_ATU_CTL_HASH_MASK
;
107 return mv88e6xxx_g1_write(chip
, MV88E6XXX_G1_ATU_CTL
, val
);
110 /* Offset 0x0B: ATU Operation Register */
112 static int mv88e6xxx_g1_atu_op_wait(struct mv88e6xxx_chip
*chip
)
114 int bit
= __bf_shf(MV88E6XXX_G1_ATU_OP_BUSY
);
116 return mv88e6xxx_g1_wait_bit(chip
, MV88E6XXX_G1_ATU_OP
, bit
, 0);
119 static int mv88e6xxx_g1_read_atu_violation(struct mv88e6xxx_chip
*chip
)
123 err
= mv88e6xxx_g1_write(chip
, MV88E6XXX_G1_ATU_OP
,
124 MV88E6XXX_G1_ATU_OP_BUSY
|
125 MV88E6XXX_G1_ATU_OP_GET_CLR_VIOLATION
);
129 return mv88e6xxx_g1_atu_op_wait(chip
);
132 static int mv88e6xxx_g1_atu_op(struct mv88e6xxx_chip
*chip
, u16 fid
, u16 op
)
137 /* FID bits are dispatched all around gradually as more are supported */
138 if (mv88e6xxx_num_databases(chip
) > 256) {
139 err
= mv88e6xxx_g1_atu_fid_write(chip
, fid
);
143 if (mv88e6xxx_num_databases(chip
) > 64) {
144 /* ATU DBNum[7:4] are located in ATU Control 15:12 */
145 err
= mv88e6xxx_g1_read(chip
, MV88E6XXX_G1_ATU_CTL
,
150 val
= (val
& 0x0fff) | ((fid
<< 8) & 0xf000);
151 err
= mv88e6xxx_g1_write(chip
, MV88E6XXX_G1_ATU_CTL
,
155 } else if (mv88e6xxx_num_databases(chip
) > 16) {
156 /* ATU DBNum[5:4] are located in ATU Operation 9:8 */
157 op
|= (fid
& 0x30) << 4;
160 /* ATU DBNum[3:0] are located in ATU Operation 3:0 */
164 err
= mv88e6xxx_g1_write(chip
, MV88E6XXX_G1_ATU_OP
,
165 MV88E6XXX_G1_ATU_OP_BUSY
| op
);
169 return mv88e6xxx_g1_atu_op_wait(chip
);
172 int mv88e6xxx_g1_atu_get_next(struct mv88e6xxx_chip
*chip
, u16 fid
)
174 return mv88e6xxx_g1_atu_op(chip
, fid
, MV88E6XXX_G1_ATU_OP_GET_NEXT_DB
);
177 static int mv88e6xxx_g1_atu_fid_read(struct mv88e6xxx_chip
*chip
, u16
*fid
)
179 u16 val
= 0, upper
= 0, op
= 0;
180 int err
= -EOPNOTSUPP
;
182 if (mv88e6xxx_num_databases(chip
) > 256) {
183 err
= mv88e6xxx_g1_read(chip
, MV88E6352_G1_ATU_FID
, &val
);
188 err
= mv88e6xxx_g1_read(chip
, MV88E6XXX_G1_ATU_OP
, &op
);
191 if (mv88e6xxx_num_databases(chip
) > 64) {
192 /* ATU DBNum[7:4] are located in ATU Control 15:12 */
193 err
= mv88e6xxx_g1_read(chip
, MV88E6XXX_G1_ATU_CTL
,
198 upper
= (upper
>> 8) & 0x00f0;
199 } else if (mv88e6xxx_num_databases(chip
) > 16) {
200 /* ATU DBNum[5:4] are located in ATU Operation 9:8 */
201 upper
= (op
>> 4) & 0x30;
204 /* ATU DBNum[3:0] are located in ATU Operation 3:0 */
205 val
= (op
& 0xf) | upper
;
212 /* Offset 0x0C: ATU Data Register */
214 static int mv88e6xxx_g1_atu_data_read(struct mv88e6xxx_chip
*chip
,
215 struct mv88e6xxx_atu_entry
*entry
)
220 err
= mv88e6xxx_g1_read(chip
, MV88E6XXX_G1_ATU_DATA
, &val
);
224 entry
->state
= val
& 0xf;
226 entry
->trunk
= !!(val
& MV88E6XXX_G1_ATU_DATA_TRUNK
);
227 entry
->portvec
= (val
>> 4) & mv88e6xxx_port_mask(chip
);
233 static int mv88e6xxx_g1_atu_data_write(struct mv88e6xxx_chip
*chip
,
234 struct mv88e6xxx_atu_entry
*entry
)
236 u16 data
= entry
->state
& 0xf;
240 data
|= MV88E6XXX_G1_ATU_DATA_TRUNK
;
242 data
|= (entry
->portvec
& mv88e6xxx_port_mask(chip
)) << 4;
245 return mv88e6xxx_g1_write(chip
, MV88E6XXX_G1_ATU_DATA
, data
);
248 /* Offset 0x0D: ATU MAC Address Register Bytes 0 & 1
249 * Offset 0x0E: ATU MAC Address Register Bytes 2 & 3
250 * Offset 0x0F: ATU MAC Address Register Bytes 4 & 5
253 static int mv88e6xxx_g1_atu_mac_read(struct mv88e6xxx_chip
*chip
,
254 struct mv88e6xxx_atu_entry
*entry
)
259 for (i
= 0; i
< 3; i
++) {
260 err
= mv88e6xxx_g1_read(chip
, MV88E6XXX_G1_ATU_MAC01
+ i
, &val
);
264 entry
->mac
[i
* 2] = val
>> 8;
265 entry
->mac
[i
* 2 + 1] = val
& 0xff;
271 static int mv88e6xxx_g1_atu_mac_write(struct mv88e6xxx_chip
*chip
,
272 struct mv88e6xxx_atu_entry
*entry
)
277 for (i
= 0; i
< 3; i
++) {
278 val
= (entry
->mac
[i
* 2] << 8) | entry
->mac
[i
* 2 + 1];
279 err
= mv88e6xxx_g1_write(chip
, MV88E6XXX_G1_ATU_MAC01
+ i
, val
);
287 /* Address Translation Unit operations */
289 int mv88e6xxx_g1_atu_getnext(struct mv88e6xxx_chip
*chip
, u16 fid
,
290 struct mv88e6xxx_atu_entry
*entry
)
294 err
= mv88e6xxx_g1_atu_op_wait(chip
);
298 /* Write the MAC address to iterate from only once */
300 err
= mv88e6xxx_g1_atu_mac_write(chip
, entry
);
305 err
= mv88e6xxx_g1_atu_op(chip
, fid
, MV88E6XXX_G1_ATU_OP_GET_NEXT_DB
);
309 err
= mv88e6xxx_g1_atu_data_read(chip
, entry
);
313 return mv88e6xxx_g1_atu_mac_read(chip
, entry
);
316 int mv88e6xxx_g1_atu_loadpurge(struct mv88e6xxx_chip
*chip
, u16 fid
,
317 struct mv88e6xxx_atu_entry
*entry
)
321 err
= mv88e6xxx_g1_atu_op_wait(chip
);
325 err
= mv88e6xxx_g1_atu_mac_write(chip
, entry
);
329 err
= mv88e6xxx_g1_atu_data_write(chip
, entry
);
333 return mv88e6xxx_g1_atu_op(chip
, fid
, MV88E6XXX_G1_ATU_OP_LOAD_DB
);
336 static int mv88e6xxx_g1_atu_flushmove(struct mv88e6xxx_chip
*chip
, u16 fid
,
337 struct mv88e6xxx_atu_entry
*entry
,
343 err
= mv88e6xxx_g1_atu_op_wait(chip
);
347 err
= mv88e6xxx_g1_atu_data_write(chip
, entry
);
351 /* Flush/Move all or non-static entries from all or a given database */
353 op
= MV88E6XXX_G1_ATU_OP_FLUSH_MOVE_ALL_DB
;
355 op
= MV88E6XXX_G1_ATU_OP_FLUSH_MOVE_NON_STATIC_DB
;
357 op
= MV88E6XXX_G1_ATU_OP_FLUSH_MOVE_ALL
;
359 op
= MV88E6XXX_G1_ATU_OP_FLUSH_MOVE_NON_STATIC
;
361 return mv88e6xxx_g1_atu_op(chip
, fid
, op
);
364 int mv88e6xxx_g1_atu_flush(struct mv88e6xxx_chip
*chip
, u16 fid
, bool all
)
366 struct mv88e6xxx_atu_entry entry
= {
367 .state
= 0, /* Null EntryState means Flush */
370 return mv88e6xxx_g1_atu_flushmove(chip
, fid
, &entry
, all
);
373 static int mv88e6xxx_g1_atu_move(struct mv88e6xxx_chip
*chip
, u16 fid
,
374 int from_port
, int to_port
, bool all
)
376 struct mv88e6xxx_atu_entry entry
= { 0 };
380 if (!chip
->info
->atu_move_port_mask
)
383 mask
= chip
->info
->atu_move_port_mask
;
384 shift
= bitmap_weight(&mask
, 16);
386 entry
.state
= 0xf; /* Full EntryState means Move */
387 entry
.portvec
= from_port
& mask
;
388 entry
.portvec
|= (to_port
& mask
) << shift
;
390 return mv88e6xxx_g1_atu_flushmove(chip
, fid
, &entry
, all
);
393 int mv88e6xxx_g1_atu_remove(struct mv88e6xxx_chip
*chip
, u16 fid
, int port
,
396 int from_port
= port
;
397 int to_port
= chip
->info
->atu_move_port_mask
;
399 return mv88e6xxx_g1_atu_move(chip
, fid
, from_port
, to_port
, all
);
402 static irqreturn_t
mv88e6xxx_g1_atu_prob_irq_thread_fn(int irq
, void *dev_id
)
404 struct mv88e6xxx_chip
*chip
= dev_id
;
405 struct mv88e6xxx_atu_entry entry
;
409 mv88e6xxx_reg_lock(chip
);
411 err
= mv88e6xxx_g1_read_atu_violation(chip
);
415 err
= mv88e6xxx_g1_read(chip
, MV88E6XXX_G1_ATU_OP
, &val
);
419 err
= mv88e6xxx_g1_atu_fid_read(chip
, &fid
);
423 err
= mv88e6xxx_g1_atu_data_read(chip
, &entry
);
427 err
= mv88e6xxx_g1_atu_mac_read(chip
, &entry
);
431 mv88e6xxx_reg_unlock(chip
);
435 if (val
& MV88E6XXX_G1_ATU_OP_MEMBER_VIOLATION
) {
436 trace_mv88e6xxx_atu_member_violation(chip
->dev
, spid
,
437 entry
.portvec
, entry
.mac
,
439 chip
->ports
[spid
].atu_member_violation
++;
442 if (val
& MV88E6XXX_G1_ATU_OP_MISS_VIOLATION
) {
443 trace_mv88e6xxx_atu_miss_violation(chip
->dev
, spid
,
444 entry
.portvec
, entry
.mac
,
446 chip
->ports
[spid
].atu_miss_violation
++;
448 if (fid
!= MV88E6XXX_FID_STANDALONE
&& chip
->ports
[spid
].mab
) {
449 err
= mv88e6xxx_handle_miss_violation(chip
, spid
,
456 if (val
& MV88E6XXX_G1_ATU_OP_FULL_VIOLATION
) {
457 trace_mv88e6xxx_atu_full_violation(chip
->dev
, spid
,
458 entry
.portvec
, entry
.mac
,
460 if (spid
< ARRAY_SIZE(chip
->ports
))
461 chip
->ports
[spid
].atu_full_violation
++;
467 mv88e6xxx_reg_unlock(chip
);
470 dev_err(chip
->dev
, "ATU problem: error %d while handling interrupt\n",
475 int mv88e6xxx_g1_atu_prob_irq_setup(struct mv88e6xxx_chip
*chip
)
479 chip
->atu_prob_irq
= irq_find_mapping(chip
->g1_irq
.domain
,
480 MV88E6XXX_G1_STS_IRQ_ATU_PROB
);
481 if (chip
->atu_prob_irq
< 0)
482 return chip
->atu_prob_irq
;
484 snprintf(chip
->atu_prob_irq_name
, sizeof(chip
->atu_prob_irq_name
),
485 "mv88e6xxx-%s-g1-atu-prob", dev_name(chip
->dev
));
487 err
= request_threaded_irq(chip
->atu_prob_irq
, NULL
,
488 mv88e6xxx_g1_atu_prob_irq_thread_fn
,
489 IRQF_ONESHOT
, chip
->atu_prob_irq_name
,
492 irq_dispose_mapping(chip
->atu_prob_irq
);
497 void mv88e6xxx_g1_atu_prob_irq_free(struct mv88e6xxx_chip
*chip
)
499 free_irq(chip
->atu_prob_irq
, chip
);
500 irq_dispose_mapping(chip
->atu_prob_irq
);