Linux Audio

Check our new training course

Linux BSP development engineering services

Need help to port Linux and bootloaders to your hardware?
Loading...
v6.13.7
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * Marvell 88E6xxx VLAN [Spanning Tree] Translation Unit (VTU [STU]) support
  4 *
  5 * Copyright (c) 2008 Marvell Semiconductor
  6 * Copyright (c) 2015 CMC Electronics, Inc.
  7 * Copyright (c) 2017 Savoir-faire Linux, Inc.
  8 */
  9
 10#include <linux/bitfield.h>
 11#include <linux/interrupt.h>
 12#include <linux/irqdomain.h>
 13
 14#include "chip.h"
 15#include "global1.h"
 16#include "trace.h"
 17
 18/* Offset 0x02: VTU FID Register */
 19
 20static int mv88e6xxx_g1_vtu_fid_read(struct mv88e6xxx_chip *chip,
 21				     struct mv88e6xxx_vtu_entry *entry)
 22{
 23	u16 val;
 24	int err;
 25
 26	err = mv88e6xxx_g1_read(chip, MV88E6352_G1_VTU_FID, &val);
 27	if (err)
 28		return err;
 29
 30	entry->fid = val & MV88E6352_G1_VTU_FID_MASK;
 31	entry->policy = !!(val & MV88E6352_G1_VTU_FID_VID_POLICY);
 32	return 0;
 33}
 34
 35static int mv88e6xxx_g1_vtu_fid_write(struct mv88e6xxx_chip *chip,
 36				      struct mv88e6xxx_vtu_entry *entry)
 37{
 38	u16 val = entry->fid & MV88E6352_G1_VTU_FID_MASK;
 39
 40	if (entry->policy)
 41		val |= MV88E6352_G1_VTU_FID_VID_POLICY;
 42
 43	return mv88e6xxx_g1_write(chip, MV88E6352_G1_VTU_FID, val);
 44}
 45
 46/* Offset 0x03: VTU SID Register */
 47
 48static int mv88e6xxx_g1_vtu_sid_read(struct mv88e6xxx_chip *chip, u8 *sid)
 
 49{
 50	u16 val;
 51	int err;
 52
 53	err = mv88e6xxx_g1_read(chip, MV88E6352_G1_VTU_SID, &val);
 54	if (err)
 55		return err;
 56
 57	*sid = val & MV88E6352_G1_VTU_SID_MASK;
 58
 59	return 0;
 60}
 61
 62static int mv88e6xxx_g1_vtu_sid_write(struct mv88e6xxx_chip *chip, u8 sid)
 
 63{
 64	u16 val = sid & MV88E6352_G1_VTU_SID_MASK;
 65
 66	return mv88e6xxx_g1_write(chip, MV88E6352_G1_VTU_SID, val);
 67}
 68
 69/* Offset 0x05: VTU Operation Register */
 70
 71static int mv88e6xxx_g1_vtu_op_wait(struct mv88e6xxx_chip *chip)
 72{
 73	int bit = __bf_shf(MV88E6XXX_G1_VTU_OP_BUSY);
 74
 75	return mv88e6xxx_g1_wait_bit(chip, MV88E6XXX_G1_VTU_OP, bit, 0);
 76}
 77
 78static int mv88e6xxx_g1_vtu_op(struct mv88e6xxx_chip *chip, u16 op)
 79{
 80	int err;
 81
 82	err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_OP,
 83				 MV88E6XXX_G1_VTU_OP_BUSY | op);
 84	if (err)
 85		return err;
 86
 87	return mv88e6xxx_g1_vtu_op_wait(chip);
 88}
 89
 90/* Offset 0x06: VTU VID Register */
 91
 92static int mv88e6xxx_g1_vtu_vid_read(struct mv88e6xxx_chip *chip,
 93				     bool *valid, u16 *vid)
 94{
 95	u16 val;
 96	int err;
 97
 98	err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_VID, &val);
 99	if (err)
100		return err;
101
102	if (vid) {
103		*vid = val & 0xfff;
104
105		if (val & MV88E6390_G1_VTU_VID_PAGE)
106			*vid |= 0x1000;
107	}
108
109	if (valid)
110		*valid = !!(val & MV88E6XXX_G1_VTU_VID_VALID);
111
112	return 0;
113}
114
115static int mv88e6xxx_g1_vtu_vid_write(struct mv88e6xxx_chip *chip,
116				      bool valid, u16 vid)
117{
118	u16 val = vid & 0xfff;
119
120	if (vid & 0x1000)
121		val |= MV88E6390_G1_VTU_VID_PAGE;
122
123	if (valid)
124		val |= MV88E6XXX_G1_VTU_VID_VALID;
125
126	return mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_VID, val);
127}
128
129/* Offset 0x07: VTU/STU Data Register 1
130 * Offset 0x08: VTU/STU Data Register 2
131 * Offset 0x09: VTU/STU Data Register 3
132 */
133static int mv88e6185_g1_vtu_stu_data_read(struct mv88e6xxx_chip *chip,
134					  u16 *regs)
135{
136	int i;
137
138	/* Read all 3 VTU/STU Data registers */
139	for (i = 0; i < 3; ++i) {
140		u16 *reg = &regs[i];
141		int err;
142
143		err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
144		if (err)
145			return err;
146	}
147
148	return 0;
149}
150
151static int mv88e6185_g1_vtu_data_read(struct mv88e6xxx_chip *chip,
152				      u8 *member, u8 *state)
153{
154	u16 regs[3];
155	int err;
156	int i;
157
158	err = mv88e6185_g1_vtu_stu_data_read(chip, regs);
159	if (err)
160		return err;
161
162	/* Extract MemberTag data */
163	for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
164		unsigned int member_offset = (i % 4) * 4;
165		unsigned int state_offset = member_offset + 2;
166
167		if (member)
168			member[i] = (regs[i / 4] >> member_offset) & 0x3;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
169
170		if (state)
171			state[i] = (regs[i / 4] >> state_offset) & 0x3;
172	}
173
174	return 0;
175}
176
177static int mv88e6185_g1_vtu_data_write(struct mv88e6xxx_chip *chip,
178				       u8 *member, u8 *state)
179{
180	u16 regs[3] = { 0 };
181	int i;
182
183	/* Insert MemberTag and PortState data */
184	for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
185		unsigned int member_offset = (i % 4) * 4;
186		unsigned int state_offset = member_offset + 2;
187
188		if (member)
189			regs[i / 4] |= (member[i] & 0x3) << member_offset;
190
191		if (state)
192			regs[i / 4] |= (state[i] & 0x3) << state_offset;
193	}
194
195	/* Write all 3 VTU/STU Data registers */
196	for (i = 0; i < 3; ++i) {
197		u16 reg = regs[i];
198		int err;
199
200		err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
201		if (err)
202			return err;
203	}
204
205	return 0;
206}
207
208static int mv88e6390_g1_vtu_data_read(struct mv88e6xxx_chip *chip, u8 *data)
209{
210	u16 regs[2];
211	int i;
212
213	/* Read the 2 VTU/STU Data registers */
214	for (i = 0; i < 2; ++i) {
215		u16 *reg = &regs[i];
216		int err;
217
218		err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
219		if (err)
220			return err;
221	}
222
223	/* Extract data */
224	for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
225		unsigned int offset = (i % 8) * 2;
226
227		data[i] = (regs[i / 8] >> offset) & 0x3;
228	}
229
230	return 0;
231}
232
233static int mv88e6390_g1_vtu_data_write(struct mv88e6xxx_chip *chip, u8 *data)
234{
235	u16 regs[2] = { 0 };
236	int i;
237
238	/* Insert data */
239	for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
240		unsigned int offset = (i % 8) * 2;
241
242		regs[i / 8] |= (data[i] & 0x3) << offset;
243	}
244
245	/* Write the 2 VTU/STU Data registers */
246	for (i = 0; i < 2; ++i) {
247		u16 reg = regs[i];
248		int err;
249
250		err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
251		if (err)
252			return err;
253	}
254
255	return 0;
256}
257
258/* VLAN Translation Unit Operations */
259
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
260int mv88e6xxx_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
261			     struct mv88e6xxx_vtu_entry *entry)
262{
263	int err;
264
265	err = mv88e6xxx_g1_vtu_op_wait(chip);
266	if (err)
267		return err;
268
269	/* To get the next higher active VID, the VTU GetNext operation can be
270	 * started again without setting the VID registers since it already
271	 * contains the last VID.
272	 *
273	 * To save a few hardware accesses and abstract this to the caller,
274	 * write the VID only once, when the entry is given as invalid.
275	 */
276	if (!entry->valid) {
277		err = mv88e6xxx_g1_vtu_vid_write(chip, false, entry->vid);
278		if (err)
279			return err;
280	}
281
282	err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_GET_NEXT);
283	if (err)
284		return err;
285
286	return mv88e6xxx_g1_vtu_vid_read(chip, &entry->valid, &entry->vid);
287}
288
289int mv88e6185_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
290			     struct mv88e6xxx_vtu_entry *entry)
291{
292	u16 val;
293	int err;
294
295	err = mv88e6xxx_g1_vtu_getnext(chip, entry);
296	if (err)
297		return err;
298
299	if (entry->valid) {
300		err = mv88e6185_g1_vtu_data_read(chip, entry->member, entry->state);
 
 
 
 
301		if (err)
302			return err;
303
304		/* VTU DBNum[3:0] are located in VTU Operation 3:0
305		 * VTU DBNum[7:4] ([5:4] for 6250) are located in VTU Operation 11:8 (9:8)
306		 */
307		err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_OP, &val);
308		if (err)
309			return err;
310
311		entry->fid = val & 0x000f;
312		entry->fid |= (val & 0x0f00) >> 4;
313		entry->fid &= mv88e6xxx_num_databases(chip) - 1;
314	}
315
316	return 0;
317}
318
319int mv88e6352_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
320			     struct mv88e6xxx_vtu_entry *entry)
321{
322	int err;
323
324	/* Fetch VLAN MemberTag data from the VTU */
325	err = mv88e6xxx_g1_vtu_getnext(chip, entry);
326	if (err)
327		return err;
328
329	if (entry->valid) {
330		err = mv88e6185_g1_vtu_data_read(chip, entry->member, NULL);
331		if (err)
332			return err;
333
334		err = mv88e6xxx_g1_vtu_fid_read(chip, entry);
335		if (err)
336			return err;
337
338		err = mv88e6xxx_g1_vtu_sid_read(chip, &entry->sid);
 
 
 
 
 
339		if (err)
340			return err;
341	}
342
343	return 0;
344}
345
346int mv88e6390_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
347			     struct mv88e6xxx_vtu_entry *entry)
348{
349	int err;
350
351	/* Fetch VLAN MemberTag data from the VTU */
352	err = mv88e6xxx_g1_vtu_getnext(chip, entry);
353	if (err)
354		return err;
355
356	if (entry->valid) {
357		err = mv88e6390_g1_vtu_data_read(chip, entry->member);
358		if (err)
359			return err;
360
361		err = mv88e6xxx_g1_vtu_fid_read(chip, entry);
 
362		if (err)
363			return err;
364
365		err = mv88e6xxx_g1_vtu_sid_read(chip, &entry->sid);
 
 
 
 
366		if (err)
367			return err;
368	}
369
370	return 0;
371}
372
373int mv88e6185_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
374			       struct mv88e6xxx_vtu_entry *entry)
375{
376	u16 op = MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE;
377	int err;
378
379	err = mv88e6xxx_g1_vtu_op_wait(chip);
380	if (err)
381		return err;
382
383	err = mv88e6xxx_g1_vtu_vid_write(chip, entry->valid, entry->vid);
384	if (err)
385		return err;
386
387	if (entry->valid) {
388		err = mv88e6185_g1_vtu_data_write(chip, entry->member, entry->state);
389		if (err)
390			return err;
391
392		/* VTU DBNum[3:0] are located in VTU Operation 3:0
393		 * VTU DBNum[7:4] are located in VTU Operation 11:8
394		 *
395		 * For the 6250/6220, the latter are really [5:4] and
396		 * 9:8, but in those cases bits 7:6 of entry->fid are
397		 * 0 since they have num_databases = 64.
398		 */
399		op |= entry->fid & 0x000f;
400		op |= (entry->fid & 0x00f0) << 4;
401	}
402
403	return mv88e6xxx_g1_vtu_op(chip, op);
404}
405
406int mv88e6352_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
407			       struct mv88e6xxx_vtu_entry *entry)
408{
409	int err;
410
411	err = mv88e6xxx_g1_vtu_op_wait(chip);
412	if (err)
413		return err;
414
415	err = mv88e6xxx_g1_vtu_vid_write(chip, entry->valid, entry->vid);
416	if (err)
417		return err;
418
419	if (entry->valid) {
420		/* Write MemberTag data */
421		err = mv88e6185_g1_vtu_data_write(chip, entry->member, NULL);
422		if (err)
423			return err;
424
425		err = mv88e6xxx_g1_vtu_fid_write(chip, entry);
 
 
 
 
 
 
426		if (err)
427			return err;
428
429		err = mv88e6xxx_g1_vtu_sid_write(chip, entry->sid);
430		if (err)
431			return err;
432	}
433
434	/* Load/Purge VTU entry */
435	return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE);
436}
437
438int mv88e6390_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
439			       struct mv88e6xxx_vtu_entry *entry)
440{
441	int err;
442
443	err = mv88e6xxx_g1_vtu_op_wait(chip);
444	if (err)
445		return err;
446
447	err = mv88e6xxx_g1_vtu_vid_write(chip, entry->valid, entry->vid);
448	if (err)
449		return err;
450
451	if (entry->valid) {
452		/* Write MemberTag data */
453		err = mv88e6390_g1_vtu_data_write(chip, entry->member);
454		if (err)
455			return err;
456
457		err = mv88e6xxx_g1_vtu_fid_write(chip, entry);
458		if (err)
459			return err;
460
461		err = mv88e6xxx_g1_vtu_sid_write(chip, entry->sid);
462		if (err)
463			return err;
464	}
465
466	/* Load/Purge VTU entry */
467	return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE);
468}
469
470int mv88e6xxx_g1_vtu_flush(struct mv88e6xxx_chip *chip)
471{
472	int err;
473
474	/* As part of the VTU flush, refresh FID map */
475	bitmap_zero(chip->fid_bitmap, MV88E6XXX_N_FID);
476
477	err = mv88e6xxx_g1_vtu_op_wait(chip);
478	if (err)
479		return err;
480
481	return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_FLUSH_ALL);
482}
483
484/* Spanning Tree Unit Operations */
485
486int mv88e6xxx_g1_stu_getnext(struct mv88e6xxx_chip *chip,
487			     struct mv88e6xxx_stu_entry *entry)
488{
489	int err;
490
491	err = mv88e6xxx_g1_vtu_op_wait(chip);
492	if (err)
493		return err;
494
495	/* To get the next higher active SID, the STU GetNext operation can be
496	 * started again without setting the SID registers since it already
497	 * contains the last SID.
498	 *
499	 * To save a few hardware accesses and abstract this to the caller,
500	 * write the SID only once, when the entry is given as invalid.
501	 */
502	if (!entry->valid) {
503		err = mv88e6xxx_g1_vtu_sid_write(chip, entry->sid);
504		if (err)
505			return err;
506	}
507
508	err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_STU_GET_NEXT);
509	if (err)
510		return err;
511
512	err = mv88e6xxx_g1_vtu_vid_read(chip, &entry->valid, NULL);
513	if (err)
514		return err;
515
516	if (entry->valid) {
517		err = mv88e6xxx_g1_vtu_sid_read(chip, &entry->sid);
518		if (err)
519			return err;
520	}
521
522	return 0;
523}
524
525int mv88e6352_g1_stu_getnext(struct mv88e6xxx_chip *chip,
526			     struct mv88e6xxx_stu_entry *entry)
527{
528	int err;
529
530	err = mv88e6xxx_g1_stu_getnext(chip, entry);
531	if (err)
532		return err;
533
534	if (!entry->valid)
535		return 0;
536
537	return mv88e6185_g1_vtu_data_read(chip, NULL, entry->state);
538}
539
540int mv88e6390_g1_stu_getnext(struct mv88e6xxx_chip *chip,
541			     struct mv88e6xxx_stu_entry *entry)
542{
543	int err;
544
545	err = mv88e6xxx_g1_stu_getnext(chip, entry);
546	if (err)
547		return err;
548
549	if (!entry->valid)
550		return 0;
551
552	return mv88e6390_g1_vtu_data_read(chip, entry->state);
553}
554
555int mv88e6352_g1_stu_loadpurge(struct mv88e6xxx_chip *chip,
556			       struct mv88e6xxx_stu_entry *entry)
557{
558	int err;
559
560	err = mv88e6xxx_g1_vtu_op_wait(chip);
561	if (err)
562		return err;
563
564	err = mv88e6xxx_g1_vtu_vid_write(chip, entry->valid, 0);
565	if (err)
566		return err;
567
568	err = mv88e6xxx_g1_vtu_sid_write(chip, entry->sid);
569	if (err)
570		return err;
571
572	if (entry->valid) {
573		err = mv88e6185_g1_vtu_data_write(chip, NULL, entry->state);
574		if (err)
575			return err;
576	}
577
578	/* Load/Purge STU entry */
579	return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_STU_LOAD_PURGE);
580}
581
582int mv88e6390_g1_stu_loadpurge(struct mv88e6xxx_chip *chip,
583			       struct mv88e6xxx_stu_entry *entry)
584{
585	int err;
586
587	err = mv88e6xxx_g1_vtu_op_wait(chip);
588	if (err)
589		return err;
590
591	err = mv88e6xxx_g1_vtu_vid_write(chip, entry->valid, 0);
592	if (err)
593		return err;
594
595	err = mv88e6xxx_g1_vtu_sid_write(chip, entry->sid);
596	if (err)
597		return err;
598
599	if (entry->valid) {
600		err = mv88e6390_g1_vtu_data_write(chip, entry->state);
601		if (err)
602			return err;
603	}
604
605	/* Load/Purge STU entry */
606	return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_STU_LOAD_PURGE);
607}
608
609/* VTU Violation Management */
610
611static irqreturn_t mv88e6xxx_g1_vtu_prob_irq_thread_fn(int irq, void *dev_id)
612{
613	struct mv88e6xxx_chip *chip = dev_id;
614	u16 val, vid;
615	int spid;
616	int err;
 
617
618	mv88e6xxx_reg_lock(chip);
619
620	err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_GET_CLR_VIOLATION);
621	if (err)
622		goto out;
623
624	err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_OP, &val);
625	if (err)
626		goto out;
627
628	err = mv88e6xxx_g1_vtu_vid_read(chip, NULL, &vid);
629	if (err)
630		goto out;
631
632	spid = val & MV88E6XXX_G1_VTU_OP_SPID_MASK;
633
634	if (val & MV88E6XXX_G1_VTU_OP_MEMBER_VIOLATION) {
635		trace_mv88e6xxx_vtu_member_violation(chip->dev, spid, vid);
 
636		chip->ports[spid].vtu_member_violation++;
637	}
638
639	if (val & MV88E6XXX_G1_VTU_OP_MISS_VIOLATION) {
640		trace_mv88e6xxx_vtu_miss_violation(chip->dev, spid, vid);
 
641		chip->ports[spid].vtu_miss_violation++;
642	}
643
644	mv88e6xxx_reg_unlock(chip);
645
646	return IRQ_HANDLED;
647
648out:
649	mv88e6xxx_reg_unlock(chip);
650
651	dev_err(chip->dev, "VTU problem: error %d while handling interrupt\n",
652		err);
653
654	return IRQ_HANDLED;
655}
656
657int mv88e6xxx_g1_vtu_prob_irq_setup(struct mv88e6xxx_chip *chip)
658{
659	int err;
660
661	chip->vtu_prob_irq = irq_find_mapping(chip->g1_irq.domain,
662					      MV88E6XXX_G1_STS_IRQ_VTU_PROB);
663	if (chip->vtu_prob_irq < 0)
664		return chip->vtu_prob_irq;
665
666	snprintf(chip->vtu_prob_irq_name, sizeof(chip->vtu_prob_irq_name),
667		 "mv88e6xxx-%s-g1-vtu-prob", dev_name(chip->dev));
668
669	err = request_threaded_irq(chip->vtu_prob_irq, NULL,
670				   mv88e6xxx_g1_vtu_prob_irq_thread_fn,
671				   IRQF_ONESHOT, chip->vtu_prob_irq_name,
672				   chip);
673	if (err)
674		irq_dispose_mapping(chip->vtu_prob_irq);
675
676	return err;
677}
678
679void mv88e6xxx_g1_vtu_prob_irq_free(struct mv88e6xxx_chip *chip)
680{
681	free_irq(chip->vtu_prob_irq, chip);
682	irq_dispose_mapping(chip->vtu_prob_irq);
683}
v5.14.15
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * Marvell 88E6xxx VLAN [Spanning Tree] Translation Unit (VTU [STU]) support
  4 *
  5 * Copyright (c) 2008 Marvell Semiconductor
  6 * Copyright (c) 2015 CMC Electronics, Inc.
  7 * Copyright (c) 2017 Savoir-faire Linux, Inc.
  8 */
  9
 10#include <linux/bitfield.h>
 11#include <linux/interrupt.h>
 12#include <linux/irqdomain.h>
 13
 14#include "chip.h"
 15#include "global1.h"
 
 16
 17/* Offset 0x02: VTU FID Register */
 18
 19static int mv88e6xxx_g1_vtu_fid_read(struct mv88e6xxx_chip *chip,
 20				     struct mv88e6xxx_vtu_entry *entry)
 21{
 22	u16 val;
 23	int err;
 24
 25	err = mv88e6xxx_g1_read(chip, MV88E6352_G1_VTU_FID, &val);
 26	if (err)
 27		return err;
 28
 29	entry->fid = val & MV88E6352_G1_VTU_FID_MASK;
 30
 31	return 0;
 32}
 33
 34static int mv88e6xxx_g1_vtu_fid_write(struct mv88e6xxx_chip *chip,
 35				      struct mv88e6xxx_vtu_entry *entry)
 36{
 37	u16 val = entry->fid & MV88E6352_G1_VTU_FID_MASK;
 38
 
 
 
 39	return mv88e6xxx_g1_write(chip, MV88E6352_G1_VTU_FID, val);
 40}
 41
 42/* Offset 0x03: VTU SID Register */
 43
 44static int mv88e6xxx_g1_vtu_sid_read(struct mv88e6xxx_chip *chip,
 45				     struct mv88e6xxx_vtu_entry *entry)
 46{
 47	u16 val;
 48	int err;
 49
 50	err = mv88e6xxx_g1_read(chip, MV88E6352_G1_VTU_SID, &val);
 51	if (err)
 52		return err;
 53
 54	entry->sid = val & MV88E6352_G1_VTU_SID_MASK;
 55
 56	return 0;
 57}
 58
 59static int mv88e6xxx_g1_vtu_sid_write(struct mv88e6xxx_chip *chip,
 60				      struct mv88e6xxx_vtu_entry *entry)
 61{
 62	u16 val = entry->sid & MV88E6352_G1_VTU_SID_MASK;
 63
 64	return mv88e6xxx_g1_write(chip, MV88E6352_G1_VTU_SID, val);
 65}
 66
 67/* Offset 0x05: VTU Operation Register */
 68
 69static int mv88e6xxx_g1_vtu_op_wait(struct mv88e6xxx_chip *chip)
 70{
 71	int bit = __bf_shf(MV88E6XXX_G1_VTU_OP_BUSY);
 72
 73	return mv88e6xxx_g1_wait_bit(chip, MV88E6XXX_G1_VTU_OP, bit, 0);
 74}
 75
 76static int mv88e6xxx_g1_vtu_op(struct mv88e6xxx_chip *chip, u16 op)
 77{
 78	int err;
 79
 80	err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_OP,
 81				 MV88E6XXX_G1_VTU_OP_BUSY | op);
 82	if (err)
 83		return err;
 84
 85	return mv88e6xxx_g1_vtu_op_wait(chip);
 86}
 87
 88/* Offset 0x06: VTU VID Register */
 89
 90static int mv88e6xxx_g1_vtu_vid_read(struct mv88e6xxx_chip *chip,
 91				     struct mv88e6xxx_vtu_entry *entry)
 92{
 93	u16 val;
 94	int err;
 95
 96	err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_VID, &val);
 97	if (err)
 98		return err;
 99
100	entry->vid = val & 0xfff;
 
101
102	if (val & MV88E6390_G1_VTU_VID_PAGE)
103		entry->vid |= 0x1000;
 
104
105	entry->valid = !!(val & MV88E6XXX_G1_VTU_VID_VALID);
 
106
107	return 0;
108}
109
110static int mv88e6xxx_g1_vtu_vid_write(struct mv88e6xxx_chip *chip,
111				      struct mv88e6xxx_vtu_entry *entry)
112{
113	u16 val = entry->vid & 0xfff;
114
115	if (entry->vid & 0x1000)
116		val |= MV88E6390_G1_VTU_VID_PAGE;
117
118	if (entry->valid)
119		val |= MV88E6XXX_G1_VTU_VID_VALID;
120
121	return mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_VID, val);
122}
123
124/* Offset 0x07: VTU/STU Data Register 1
125 * Offset 0x08: VTU/STU Data Register 2
126 * Offset 0x09: VTU/STU Data Register 3
127 */
128static int mv88e6185_g1_vtu_stu_data_read(struct mv88e6xxx_chip *chip,
129					  u16 *regs)
130{
131	int i;
132
133	/* Read all 3 VTU/STU Data registers */
134	for (i = 0; i < 3; ++i) {
135		u16 *reg = &regs[i];
136		int err;
137
138		err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
139		if (err)
140			return err;
141	}
142
143	return 0;
144}
145
146static int mv88e6185_g1_vtu_data_read(struct mv88e6xxx_chip *chip,
147				      struct mv88e6xxx_vtu_entry *entry)
148{
149	u16 regs[3];
150	int err;
151	int i;
152
153	err = mv88e6185_g1_vtu_stu_data_read(chip, regs);
154	if (err)
155		return err;
156
157	/* Extract MemberTag data */
158	for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
159		unsigned int member_offset = (i % 4) * 4;
 
160
161		entry->member[i] = (regs[i / 4] >> member_offset) & 0x3;
162	}
163
164	return 0;
165}
166
167static int mv88e6185_g1_stu_data_read(struct mv88e6xxx_chip *chip,
168				      struct mv88e6xxx_vtu_entry *entry)
169{
170	u16 regs[3];
171	int err;
172	int i;
173
174	err = mv88e6185_g1_vtu_stu_data_read(chip, regs);
175	if (err)
176		return err;
177
178	/* Extract PortState data */
179	for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
180		unsigned int state_offset = (i % 4) * 4 + 2;
181
182		entry->state[i] = (regs[i / 4] >> state_offset) & 0x3;
 
183	}
184
185	return 0;
186}
187
188static int mv88e6185_g1_vtu_data_write(struct mv88e6xxx_chip *chip,
189				       struct mv88e6xxx_vtu_entry *entry)
190{
191	u16 regs[3] = { 0 };
192	int i;
193
194	/* Insert MemberTag and PortState data */
195	for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
196		unsigned int member_offset = (i % 4) * 4;
197		unsigned int state_offset = member_offset + 2;
198
199		regs[i / 4] |= (entry->member[i] & 0x3) << member_offset;
200		regs[i / 4] |= (entry->state[i] & 0x3) << state_offset;
 
 
 
201	}
202
203	/* Write all 3 VTU/STU Data registers */
204	for (i = 0; i < 3; ++i) {
205		u16 reg = regs[i];
206		int err;
207
208		err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
209		if (err)
210			return err;
211	}
212
213	return 0;
214}
215
216static int mv88e6390_g1_vtu_data_read(struct mv88e6xxx_chip *chip, u8 *data)
217{
218	u16 regs[2];
219	int i;
220
221	/* Read the 2 VTU/STU Data registers */
222	for (i = 0; i < 2; ++i) {
223		u16 *reg = &regs[i];
224		int err;
225
226		err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
227		if (err)
228			return err;
229	}
230
231	/* Extract data */
232	for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
233		unsigned int offset = (i % 8) * 2;
234
235		data[i] = (regs[i / 8] >> offset) & 0x3;
236	}
237
238	return 0;
239}
240
241static int mv88e6390_g1_vtu_data_write(struct mv88e6xxx_chip *chip, u8 *data)
242{
243	u16 regs[2] = { 0 };
244	int i;
245
246	/* Insert data */
247	for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
248		unsigned int offset = (i % 8) * 2;
249
250		regs[i / 8] |= (data[i] & 0x3) << offset;
251	}
252
253	/* Write the 2 VTU/STU Data registers */
254	for (i = 0; i < 2; ++i) {
255		u16 reg = regs[i];
256		int err;
257
258		err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
259		if (err)
260			return err;
261	}
262
263	return 0;
264}
265
266/* VLAN Translation Unit Operations */
267
268static int mv88e6xxx_g1_vtu_stu_getnext(struct mv88e6xxx_chip *chip,
269					struct mv88e6xxx_vtu_entry *entry)
270{
271	int err;
272
273	err = mv88e6xxx_g1_vtu_sid_write(chip, entry);
274	if (err)
275		return err;
276
277	err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_STU_GET_NEXT);
278	if (err)
279		return err;
280
281	err = mv88e6xxx_g1_vtu_sid_read(chip, entry);
282	if (err)
283		return err;
284
285	return mv88e6xxx_g1_vtu_vid_read(chip, entry);
286}
287
288static int mv88e6xxx_g1_vtu_stu_get(struct mv88e6xxx_chip *chip,
289				    struct mv88e6xxx_vtu_entry *vtu)
290{
291	struct mv88e6xxx_vtu_entry stu;
292	int err;
293
294	err = mv88e6xxx_g1_vtu_sid_read(chip, vtu);
295	if (err)
296		return err;
297
298	stu.sid = vtu->sid - 1;
299
300	err = mv88e6xxx_g1_vtu_stu_getnext(chip, &stu);
301	if (err)
302		return err;
303
304	if (stu.sid != vtu->sid || !stu.valid)
305		return -EINVAL;
306
307	return 0;
308}
309
310int mv88e6xxx_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
311			     struct mv88e6xxx_vtu_entry *entry)
312{
313	int err;
314
315	err = mv88e6xxx_g1_vtu_op_wait(chip);
316	if (err)
317		return err;
318
319	/* To get the next higher active VID, the VTU GetNext operation can be
320	 * started again without setting the VID registers since it already
321	 * contains the last VID.
322	 *
323	 * To save a few hardware accesses and abstract this to the caller,
324	 * write the VID only once, when the entry is given as invalid.
325	 */
326	if (!entry->valid) {
327		err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
328		if (err)
329			return err;
330	}
331
332	err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_GET_NEXT);
333	if (err)
334		return err;
335
336	return mv88e6xxx_g1_vtu_vid_read(chip, entry);
337}
338
339int mv88e6185_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
340			     struct mv88e6xxx_vtu_entry *entry)
341{
342	u16 val;
343	int err;
344
345	err = mv88e6xxx_g1_vtu_getnext(chip, entry);
346	if (err)
347		return err;
348
349	if (entry->valid) {
350		err = mv88e6185_g1_vtu_data_read(chip, entry);
351		if (err)
352			return err;
353
354		err = mv88e6185_g1_stu_data_read(chip, entry);
355		if (err)
356			return err;
357
358		/* VTU DBNum[3:0] are located in VTU Operation 3:0
359		 * VTU DBNum[7:4] ([5:4] for 6250) are located in VTU Operation 11:8 (9:8)
360		 */
361		err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_OP, &val);
362		if (err)
363			return err;
364
365		entry->fid = val & 0x000f;
366		entry->fid |= (val & 0x0f00) >> 4;
367		entry->fid &= mv88e6xxx_num_databases(chip) - 1;
368	}
369
370	return 0;
371}
372
373int mv88e6352_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
374			     struct mv88e6xxx_vtu_entry *entry)
375{
376	int err;
377
378	/* Fetch VLAN MemberTag data from the VTU */
379	err = mv88e6xxx_g1_vtu_getnext(chip, entry);
380	if (err)
381		return err;
382
383	if (entry->valid) {
384		err = mv88e6185_g1_vtu_data_read(chip, entry);
385		if (err)
386			return err;
387
388		err = mv88e6xxx_g1_vtu_fid_read(chip, entry);
389		if (err)
390			return err;
391
392		/* Fetch VLAN PortState data from the STU */
393		err = mv88e6xxx_g1_vtu_stu_get(chip, entry);
394		if (err)
395			return err;
396
397		err = mv88e6185_g1_stu_data_read(chip, entry);
398		if (err)
399			return err;
400	}
401
402	return 0;
403}
404
405int mv88e6390_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
406			     struct mv88e6xxx_vtu_entry *entry)
407{
408	int err;
409
410	/* Fetch VLAN MemberTag data from the VTU */
411	err = mv88e6xxx_g1_vtu_getnext(chip, entry);
412	if (err)
413		return err;
414
415	if (entry->valid) {
416		err = mv88e6390_g1_vtu_data_read(chip, entry->member);
417		if (err)
418			return err;
419
420		/* Fetch VLAN PortState data from the STU */
421		err = mv88e6xxx_g1_vtu_stu_get(chip, entry);
422		if (err)
423			return err;
424
425		err = mv88e6390_g1_vtu_data_read(chip, entry->state);
426		if (err)
427			return err;
428
429		err = mv88e6xxx_g1_vtu_fid_read(chip, entry);
430		if (err)
431			return err;
432	}
433
434	return 0;
435}
436
437int mv88e6185_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
438			       struct mv88e6xxx_vtu_entry *entry)
439{
440	u16 op = MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE;
441	int err;
442
443	err = mv88e6xxx_g1_vtu_op_wait(chip);
444	if (err)
445		return err;
446
447	err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
448	if (err)
449		return err;
450
451	if (entry->valid) {
452		err = mv88e6185_g1_vtu_data_write(chip, entry);
453		if (err)
454			return err;
455
456		/* VTU DBNum[3:0] are located in VTU Operation 3:0
457		 * VTU DBNum[7:4] are located in VTU Operation 11:8
458		 *
459		 * For the 6250/6220, the latter are really [5:4] and
460		 * 9:8, but in those cases bits 7:6 of entry->fid are
461		 * 0 since they have num_databases = 64.
462		 */
463		op |= entry->fid & 0x000f;
464		op |= (entry->fid & 0x00f0) << 4;
465	}
466
467	return mv88e6xxx_g1_vtu_op(chip, op);
468}
469
470int mv88e6352_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
471			       struct mv88e6xxx_vtu_entry *entry)
472{
473	int err;
474
475	err = mv88e6xxx_g1_vtu_op_wait(chip);
476	if (err)
477		return err;
478
479	err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
480	if (err)
481		return err;
482
483	if (entry->valid) {
484		/* Write MemberTag and PortState data */
485		err = mv88e6185_g1_vtu_data_write(chip, entry);
486		if (err)
487			return err;
488
489		err = mv88e6xxx_g1_vtu_sid_write(chip, entry);
490		if (err)
491			return err;
492
493		/* Load STU entry */
494		err = mv88e6xxx_g1_vtu_op(chip,
495					  MV88E6XXX_G1_VTU_OP_STU_LOAD_PURGE);
496		if (err)
497			return err;
498
499		err = mv88e6xxx_g1_vtu_fid_write(chip, entry);
500		if (err)
501			return err;
502	}
503
504	/* Load/Purge VTU entry */
505	return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE);
506}
507
508int mv88e6390_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
509			       struct mv88e6xxx_vtu_entry *entry)
510{
511	int err;
512
513	err = mv88e6xxx_g1_vtu_op_wait(chip);
514	if (err)
515		return err;
516
517	err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
518	if (err)
519		return err;
520
521	if (entry->valid) {
522		/* Write PortState data */
523		err = mv88e6390_g1_vtu_data_write(chip, entry->state);
 
 
 
 
524		if (err)
525			return err;
526
527		err = mv88e6xxx_g1_vtu_sid_write(chip, entry);
528		if (err)
529			return err;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
530
531		/* Load STU entry */
532		err = mv88e6xxx_g1_vtu_op(chip,
533					  MV88E6XXX_G1_VTU_OP_STU_LOAD_PURGE);
 
 
 
 
 
 
534		if (err)
535			return err;
 
536
537		/* Write MemberTag data */
538		err = mv88e6390_g1_vtu_data_write(chip, entry->member);
 
 
 
 
 
 
 
 
539		if (err)
540			return err;
 
541
542		err = mv88e6xxx_g1_vtu_fid_write(chip, entry);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
543		if (err)
544			return err;
545	}
546
547	/* Load/Purge VTU entry */
548	return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE);
549}
550
551int mv88e6xxx_g1_vtu_flush(struct mv88e6xxx_chip *chip)
 
552{
553	int err;
554
555	err = mv88e6xxx_g1_vtu_op_wait(chip);
556	if (err)
557		return err;
558
559	return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_FLUSH_ALL);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
560}
561
 
 
562static irqreturn_t mv88e6xxx_g1_vtu_prob_irq_thread_fn(int irq, void *dev_id)
563{
564	struct mv88e6xxx_chip *chip = dev_id;
565	struct mv88e6xxx_vtu_entry entry;
566	int spid;
567	int err;
568	u16 val;
569
570	mv88e6xxx_reg_lock(chip);
571
572	err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_GET_CLR_VIOLATION);
573	if (err)
574		goto out;
575
576	err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_OP, &val);
577	if (err)
578		goto out;
579
580	err = mv88e6xxx_g1_vtu_vid_read(chip, &entry);
581	if (err)
582		goto out;
583
584	spid = val & MV88E6XXX_G1_VTU_OP_SPID_MASK;
585
586	if (val & MV88E6XXX_G1_VTU_OP_MEMBER_VIOLATION) {
587		dev_err_ratelimited(chip->dev, "VTU member violation for vid %d, source port %d\n",
588				    entry.vid, spid);
589		chip->ports[spid].vtu_member_violation++;
590	}
591
592	if (val & MV88E6XXX_G1_VTU_OP_MISS_VIOLATION) {
593		dev_dbg_ratelimited(chip->dev, "VTU miss violation for vid %d, source port %d\n",
594				    entry.vid, spid);
595		chip->ports[spid].vtu_miss_violation++;
596	}
597
598	mv88e6xxx_reg_unlock(chip);
599
600	return IRQ_HANDLED;
601
602out:
603	mv88e6xxx_reg_unlock(chip);
604
605	dev_err(chip->dev, "VTU problem: error %d while handling interrupt\n",
606		err);
607
608	return IRQ_HANDLED;
609}
610
611int mv88e6xxx_g1_vtu_prob_irq_setup(struct mv88e6xxx_chip *chip)
612{
613	int err;
614
615	chip->vtu_prob_irq = irq_find_mapping(chip->g1_irq.domain,
616					      MV88E6XXX_G1_STS_IRQ_VTU_PROB);
617	if (chip->vtu_prob_irq < 0)
618		return chip->vtu_prob_irq;
619
620	snprintf(chip->vtu_prob_irq_name, sizeof(chip->vtu_prob_irq_name),
621		 "mv88e6xxx-%s-g1-vtu-prob", dev_name(chip->dev));
622
623	err = request_threaded_irq(chip->vtu_prob_irq, NULL,
624				   mv88e6xxx_g1_vtu_prob_irq_thread_fn,
625				   IRQF_ONESHOT, chip->vtu_prob_irq_name,
626				   chip);
627	if (err)
628		irq_dispose_mapping(chip->vtu_prob_irq);
629
630	return err;
631}
632
633void mv88e6xxx_g1_vtu_prob_irq_free(struct mv88e6xxx_chip *chip)
634{
635	free_irq(chip->vtu_prob_irq, chip);
636	irq_dispose_mapping(chip->vtu_prob_irq);
637}