Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  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}