Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1/*
  2 * Marvell 88E6xxx Switch Port Registers support
  3 *
  4 * Copyright (c) 2008 Marvell Semiconductor
  5 *
  6 * Copyright (c) 2016-2017 Savoir-faire Linux Inc.
  7 *	Vivien Didelot <vivien.didelot@savoirfairelinux.com>
  8 *
  9 * This program is free software; you can redistribute it and/or modify
 10 * it under the terms of the GNU General Public License as published by
 11 * the Free Software Foundation; either version 2 of the License, or
 12 * (at your option) any later version.
 13 */
 14
 15#include <linux/bitfield.h>
 16#include <linux/if_bridge.h>
 17#include <linux/phy.h>
 18
 19#include "chip.h"
 20#include "port.h"
 21
 22int mv88e6xxx_port_read(struct mv88e6xxx_chip *chip, int port, int reg,
 23			u16 *val)
 24{
 25	int addr = chip->info->port_base_addr + port;
 26
 27	return mv88e6xxx_read(chip, addr, reg, val);
 28}
 29
 30int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg,
 31			 u16 val)
 32{
 33	int addr = chip->info->port_base_addr + port;
 34
 35	return mv88e6xxx_write(chip, addr, reg, val);
 36}
 37
 38/* Offset 0x01: MAC (or PCS or Physical) Control Register
 39 *
 40 * Link, Duplex and Flow Control have one force bit, one value bit.
 41 *
 42 * For port's MAC speed, ForceSpd (or SpdValue) bits 1:0 program the value.
 43 * Alternative values require the 200BASE (or AltSpeed) bit 12 set.
 44 * Newer chips need a ForcedSpd bit 13 set to consider the value.
 45 */
 46
 47static int mv88e6xxx_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port,
 48					  phy_interface_t mode)
 49{
 50	u16 reg;
 51	int err;
 52
 53	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_MAC_CTL, &reg);
 54	if (err)
 55		return err;
 56
 57	reg &= ~(MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_RXCLK |
 58		 MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_TXCLK);
 59
 60	switch (mode) {
 61	case PHY_INTERFACE_MODE_RGMII_RXID:
 62		reg |= MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_RXCLK;
 63		break;
 64	case PHY_INTERFACE_MODE_RGMII_TXID:
 65		reg |= MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_TXCLK;
 66		break;
 67	case PHY_INTERFACE_MODE_RGMII_ID:
 68		reg |= MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_RXCLK |
 69			MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_TXCLK;
 70		break;
 71	case PHY_INTERFACE_MODE_RGMII:
 72		break;
 73	default:
 74		return 0;
 75	}
 76
 77	err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_MAC_CTL, reg);
 78	if (err)
 79		return err;
 80
 81	dev_dbg(chip->dev, "p%d: delay RXCLK %s, TXCLK %s\n", port,
 82		reg & MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_RXCLK ? "yes" : "no",
 83		reg & MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_TXCLK ? "yes" : "no");
 84
 85	return 0;
 86}
 87
 88int mv88e6352_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port,
 89				   phy_interface_t mode)
 90{
 91	if (port < 5)
 92		return -EOPNOTSUPP;
 93
 94	return mv88e6xxx_port_set_rgmii_delay(chip, port, mode);
 95}
 96
 97int mv88e6390_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port,
 98				   phy_interface_t mode)
 99{
100	if (port != 0)
101		return -EOPNOTSUPP;
102
103	return mv88e6xxx_port_set_rgmii_delay(chip, port, mode);
104}
105
106int mv88e6xxx_port_set_link(struct mv88e6xxx_chip *chip, int port, int link)
107{
108	u16 reg;
109	int err;
110
111	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_MAC_CTL, &reg);
112	if (err)
113		return err;
114
115	reg &= ~(MV88E6XXX_PORT_MAC_CTL_FORCE_LINK |
116		 MV88E6XXX_PORT_MAC_CTL_LINK_UP);
117
118	switch (link) {
119	case LINK_FORCED_DOWN:
120		reg |= MV88E6XXX_PORT_MAC_CTL_FORCE_LINK;
121		break;
122	case LINK_FORCED_UP:
123		reg |= MV88E6XXX_PORT_MAC_CTL_FORCE_LINK |
124			MV88E6XXX_PORT_MAC_CTL_LINK_UP;
125		break;
126	case LINK_UNFORCED:
127		/* normal link detection */
128		break;
129	default:
130		return -EINVAL;
131	}
132
133	err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_MAC_CTL, reg);
134	if (err)
135		return err;
136
137	dev_dbg(chip->dev, "p%d: %s link %s\n", port,
138		reg & MV88E6XXX_PORT_MAC_CTL_FORCE_LINK ? "Force" : "Unforce",
139		reg & MV88E6XXX_PORT_MAC_CTL_LINK_UP ? "up" : "down");
140
141	return 0;
142}
143
144int mv88e6xxx_port_set_duplex(struct mv88e6xxx_chip *chip, int port, int dup)
145{
146	u16 reg;
147	int err;
148
149	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_MAC_CTL, &reg);
150	if (err)
151		return err;
152
153	reg &= ~(MV88E6XXX_PORT_MAC_CTL_FORCE_DUPLEX |
154		 MV88E6XXX_PORT_MAC_CTL_DUPLEX_FULL);
155
156	switch (dup) {
157	case DUPLEX_HALF:
158		reg |= MV88E6XXX_PORT_MAC_CTL_FORCE_DUPLEX;
159		break;
160	case DUPLEX_FULL:
161		reg |= MV88E6XXX_PORT_MAC_CTL_FORCE_DUPLEX |
162			MV88E6XXX_PORT_MAC_CTL_DUPLEX_FULL;
163		break;
164	case DUPLEX_UNFORCED:
165		/* normal duplex detection */
166		break;
167	default:
168		return -EINVAL;
169	}
170
171	err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_MAC_CTL, reg);
172	if (err)
173		return err;
174
175	dev_dbg(chip->dev, "p%d: %s %s duplex\n", port,
176		reg & MV88E6XXX_PORT_MAC_CTL_FORCE_DUPLEX ? "Force" : "Unforce",
177		reg & MV88E6XXX_PORT_MAC_CTL_DUPLEX_FULL ? "full" : "half");
178
179	return 0;
180}
181
182static int mv88e6xxx_port_set_speed(struct mv88e6xxx_chip *chip, int port,
183				    int speed, bool alt_bit, bool force_bit)
184{
185	u16 reg, ctrl;
186	int err;
187
188	switch (speed) {
189	case 10:
190		ctrl = MV88E6XXX_PORT_MAC_CTL_SPEED_10;
191		break;
192	case 100:
193		ctrl = MV88E6XXX_PORT_MAC_CTL_SPEED_100;
194		break;
195	case 200:
196		if (alt_bit)
197			ctrl = MV88E6XXX_PORT_MAC_CTL_SPEED_100 |
198				MV88E6390_PORT_MAC_CTL_ALTSPEED;
199		else
200			ctrl = MV88E6065_PORT_MAC_CTL_SPEED_200;
201		break;
202	case 1000:
203		ctrl = MV88E6XXX_PORT_MAC_CTL_SPEED_1000;
204		break;
205	case 2500:
206		ctrl = MV88E6390_PORT_MAC_CTL_SPEED_10000 |
207			MV88E6390_PORT_MAC_CTL_ALTSPEED;
208		break;
209	case 10000:
210		/* all bits set, fall through... */
211	case SPEED_UNFORCED:
212		ctrl = MV88E6XXX_PORT_MAC_CTL_SPEED_UNFORCED;
213		break;
214	default:
215		return -EOPNOTSUPP;
216	}
217
218	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_MAC_CTL, &reg);
219	if (err)
220		return err;
221
222	reg &= ~MV88E6XXX_PORT_MAC_CTL_SPEED_MASK;
223	if (alt_bit)
224		reg &= ~MV88E6390_PORT_MAC_CTL_ALTSPEED;
225	if (force_bit) {
226		reg &= ~MV88E6390_PORT_MAC_CTL_FORCE_SPEED;
227		if (speed != SPEED_UNFORCED)
228			ctrl |= MV88E6390_PORT_MAC_CTL_FORCE_SPEED;
229	}
230	reg |= ctrl;
231
232	err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_MAC_CTL, reg);
233	if (err)
234		return err;
235
236	if (speed)
237		dev_dbg(chip->dev, "p%d: Speed set to %d Mbps\n", port, speed);
238	else
239		dev_dbg(chip->dev, "p%d: Speed unforced\n", port);
240
241	return 0;
242}
243
244/* Support 10, 100, 200 Mbps (e.g. 88E6065 family) */
245int mv88e6065_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
246{
247	if (speed == SPEED_MAX)
248		speed = 200;
249
250	if (speed > 200)
251		return -EOPNOTSUPP;
252
253	/* Setting 200 Mbps on port 0 to 3 selects 100 Mbps */
254	return mv88e6xxx_port_set_speed(chip, port, speed, false, false);
255}
256
257/* Support 10, 100, 1000 Mbps (e.g. 88E6185 family) */
258int mv88e6185_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
259{
260	if (speed == SPEED_MAX)
261		speed = 1000;
262
263	if (speed == 200 || speed > 1000)
264		return -EOPNOTSUPP;
265
266	return mv88e6xxx_port_set_speed(chip, port, speed, false, false);
267}
268
269/* Support 10, 100, 200, 1000 Mbps (e.g. 88E6352 family) */
270int mv88e6352_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
271{
272	if (speed == SPEED_MAX)
273		speed = 1000;
274
275	if (speed > 1000)
276		return -EOPNOTSUPP;
277
278	if (speed == 200 && port < 5)
279		return -EOPNOTSUPP;
280
281	return mv88e6xxx_port_set_speed(chip, port, speed, true, false);
282}
283
284/* Support 10, 100, 200, 1000, 2500 Mbps (e.g. 88E6390) */
285int mv88e6390_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
286{
287	if (speed == SPEED_MAX)
288		speed = port < 9 ? 1000 : 2500;
289
290	if (speed > 2500)
291		return -EOPNOTSUPP;
292
293	if (speed == 200 && port != 0)
294		return -EOPNOTSUPP;
295
296	if (speed == 2500 && port < 9)
297		return -EOPNOTSUPP;
298
299	return mv88e6xxx_port_set_speed(chip, port, speed, true, true);
300}
301
302/* Support 10, 100, 200, 1000, 2500, 10000 Mbps (e.g. 88E6190X) */
303int mv88e6390x_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
304{
305	if (speed == SPEED_MAX)
306		speed = port < 9 ? 1000 : 10000;
307
308	if (speed == 200 && port != 0)
309		return -EOPNOTSUPP;
310
311	if (speed >= 2500 && port < 9)
312		return -EOPNOTSUPP;
313
314	return mv88e6xxx_port_set_speed(chip, port, speed, true, true);
315}
316
317int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
318			      phy_interface_t mode)
319{
320	u16 reg;
321	u16 cmode;
322	int err;
323
324	if (mode == PHY_INTERFACE_MODE_NA)
325		return 0;
326
327	if (port != 9 && port != 10)
328		return -EOPNOTSUPP;
329
330	switch (mode) {
331	case PHY_INTERFACE_MODE_1000BASEX:
332		cmode = MV88E6XXX_PORT_STS_CMODE_1000BASE_X;
333		break;
334	case PHY_INTERFACE_MODE_SGMII:
335		cmode = MV88E6XXX_PORT_STS_CMODE_SGMII;
336		break;
337	case PHY_INTERFACE_MODE_2500BASEX:
338		cmode = MV88E6XXX_PORT_STS_CMODE_2500BASEX;
339		break;
340	case PHY_INTERFACE_MODE_XGMII:
341	case PHY_INTERFACE_MODE_XAUI:
342		cmode = MV88E6XXX_PORT_STS_CMODE_XAUI;
343		break;
344	case PHY_INTERFACE_MODE_RXAUI:
345		cmode = MV88E6XXX_PORT_STS_CMODE_RXAUI;
346		break;
347	default:
348		cmode = 0;
349	}
350
351	if (cmode) {
352		err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &reg);
353		if (err)
354			return err;
355
356		reg &= ~MV88E6XXX_PORT_STS_CMODE_MASK;
357		reg |= cmode;
358
359		err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_STS, reg);
360		if (err)
361			return err;
362	}
363
364	return 0;
365}
366
367int mv88e6xxx_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode)
368{
369	int err;
370	u16 reg;
371
372	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &reg);
373	if (err)
374		return err;
375
376	*cmode = reg & MV88E6XXX_PORT_STS_CMODE_MASK;
377
378	return 0;
379}
380
381/* Offset 0x02: Jamming Control
382 *
383 * Do not limit the period of time that this port can be paused for by
384 * the remote end or the period of time that this port can pause the
385 * remote end.
386 */
387int mv88e6097_port_pause_limit(struct mv88e6xxx_chip *chip, int port, u8 in,
388			       u8 out)
389{
390	return mv88e6xxx_port_write(chip, port, MV88E6097_PORT_JAM_CTL,
391				    out << 8 | in);
392}
393
394int mv88e6390_port_pause_limit(struct mv88e6xxx_chip *chip, int port, u8 in,
395			       u8 out)
396{
397	int err;
398
399	err = mv88e6xxx_port_write(chip, port, MV88E6390_PORT_FLOW_CTL,
400				   MV88E6390_PORT_FLOW_CTL_UPDATE |
401				   MV88E6390_PORT_FLOW_CTL_LIMIT_IN | in);
402	if (err)
403		return err;
404
405	return mv88e6xxx_port_write(chip, port, MV88E6390_PORT_FLOW_CTL,
406				    MV88E6390_PORT_FLOW_CTL_UPDATE |
407				    MV88E6390_PORT_FLOW_CTL_LIMIT_OUT | out);
408}
409
410/* Offset 0x04: Port Control Register */
411
412static const char * const mv88e6xxx_port_state_names[] = {
413	[MV88E6XXX_PORT_CTL0_STATE_DISABLED] = "Disabled",
414	[MV88E6XXX_PORT_CTL0_STATE_BLOCKING] = "Blocking/Listening",
415	[MV88E6XXX_PORT_CTL0_STATE_LEARNING] = "Learning",
416	[MV88E6XXX_PORT_CTL0_STATE_FORWARDING] = "Forwarding",
417};
418
419int mv88e6xxx_port_set_state(struct mv88e6xxx_chip *chip, int port, u8 state)
420{
421	u16 reg;
422	int err;
423
424	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL0, &reg);
425	if (err)
426		return err;
427
428	reg &= ~MV88E6XXX_PORT_CTL0_STATE_MASK;
429
430	switch (state) {
431	case BR_STATE_DISABLED:
432		state = MV88E6XXX_PORT_CTL0_STATE_DISABLED;
433		break;
434	case BR_STATE_BLOCKING:
435	case BR_STATE_LISTENING:
436		state = MV88E6XXX_PORT_CTL0_STATE_BLOCKING;
437		break;
438	case BR_STATE_LEARNING:
439		state = MV88E6XXX_PORT_CTL0_STATE_LEARNING;
440		break;
441	case BR_STATE_FORWARDING:
442		state = MV88E6XXX_PORT_CTL0_STATE_FORWARDING;
443		break;
444	default:
445		return -EINVAL;
446	}
447
448	reg |= state;
449
450	err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
451	if (err)
452		return err;
453
454	dev_dbg(chip->dev, "p%d: PortState set to %s\n", port,
455		mv88e6xxx_port_state_names[state]);
456
457	return 0;
458}
459
460int mv88e6xxx_port_set_egress_mode(struct mv88e6xxx_chip *chip, int port,
461				   enum mv88e6xxx_egress_mode mode)
462{
463	int err;
464	u16 reg;
465
466	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL0, &reg);
467	if (err)
468		return err;
469
470	reg &= ~MV88E6XXX_PORT_CTL0_EGRESS_MODE_MASK;
471
472	switch (mode) {
473	case MV88E6XXX_EGRESS_MODE_UNMODIFIED:
474		reg |= MV88E6XXX_PORT_CTL0_EGRESS_MODE_UNMODIFIED;
475		break;
476	case MV88E6XXX_EGRESS_MODE_UNTAGGED:
477		reg |= MV88E6XXX_PORT_CTL0_EGRESS_MODE_UNTAGGED;
478		break;
479	case MV88E6XXX_EGRESS_MODE_TAGGED:
480		reg |= MV88E6XXX_PORT_CTL0_EGRESS_MODE_TAGGED;
481		break;
482	case MV88E6XXX_EGRESS_MODE_ETHERTYPE:
483		reg |= MV88E6XXX_PORT_CTL0_EGRESS_MODE_ETHER_TYPE_DSA;
484		break;
485	default:
486		return -EINVAL;
487	}
488
489	return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
490}
491
492int mv88e6085_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port,
493				  enum mv88e6xxx_frame_mode mode)
494{
495	int err;
496	u16 reg;
497
498	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL0, &reg);
499	if (err)
500		return err;
501
502	reg &= ~MV88E6XXX_PORT_CTL0_FRAME_MODE_MASK;
503
504	switch (mode) {
505	case MV88E6XXX_FRAME_MODE_NORMAL:
506		reg |= MV88E6XXX_PORT_CTL0_FRAME_MODE_NORMAL;
507		break;
508	case MV88E6XXX_FRAME_MODE_DSA:
509		reg |= MV88E6XXX_PORT_CTL0_FRAME_MODE_DSA;
510		break;
511	default:
512		return -EINVAL;
513	}
514
515	return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
516}
517
518int mv88e6351_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port,
519				  enum mv88e6xxx_frame_mode mode)
520{
521	int err;
522	u16 reg;
523
524	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL0, &reg);
525	if (err)
526		return err;
527
528	reg &= ~MV88E6XXX_PORT_CTL0_FRAME_MODE_MASK;
529
530	switch (mode) {
531	case MV88E6XXX_FRAME_MODE_NORMAL:
532		reg |= MV88E6XXX_PORT_CTL0_FRAME_MODE_NORMAL;
533		break;
534	case MV88E6XXX_FRAME_MODE_DSA:
535		reg |= MV88E6XXX_PORT_CTL0_FRAME_MODE_DSA;
536		break;
537	case MV88E6XXX_FRAME_MODE_PROVIDER:
538		reg |= MV88E6XXX_PORT_CTL0_FRAME_MODE_PROVIDER;
539		break;
540	case MV88E6XXX_FRAME_MODE_ETHERTYPE:
541		reg |= MV88E6XXX_PORT_CTL0_FRAME_MODE_ETHER_TYPE_DSA;
542		break;
543	default:
544		return -EINVAL;
545	}
546
547	return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
548}
549
550static int mv88e6185_port_set_forward_unknown(struct mv88e6xxx_chip *chip,
551					      int port, bool unicast)
552{
553	int err;
554	u16 reg;
555
556	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL0, &reg);
557	if (err)
558		return err;
559
560	if (unicast)
561		reg |= MV88E6185_PORT_CTL0_FORWARD_UNKNOWN;
562	else
563		reg &= ~MV88E6185_PORT_CTL0_FORWARD_UNKNOWN;
564
565	return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
566}
567
568int mv88e6352_port_set_egress_floods(struct mv88e6xxx_chip *chip, int port,
569				     bool unicast, bool multicast)
570{
571	int err;
572	u16 reg;
573
574	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL0, &reg);
575	if (err)
576		return err;
577
578	reg &= ~MV88E6352_PORT_CTL0_EGRESS_FLOODS_MASK;
579
580	if (unicast && multicast)
581		reg |= MV88E6352_PORT_CTL0_EGRESS_FLOODS_ALL_UNKNOWN_DA;
582	else if (unicast)
583		reg |= MV88E6352_PORT_CTL0_EGRESS_FLOODS_NO_UNKNOWN_MC_DA;
584	else if (multicast)
585		reg |= MV88E6352_PORT_CTL0_EGRESS_FLOODS_NO_UNKNOWN_UC_DA;
586	else
587		reg |= MV88E6352_PORT_CTL0_EGRESS_FLOODS_NO_UNKNOWN_DA;
588
589	return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
590}
591
592/* Offset 0x05: Port Control 1 */
593
594int mv88e6xxx_port_set_message_port(struct mv88e6xxx_chip *chip, int port,
595				    bool message_port)
596{
597	u16 val;
598	int err;
599
600	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL1, &val);
601	if (err)
602		return err;
603
604	if (message_port)
605		val |= MV88E6XXX_PORT_CTL1_MESSAGE_PORT;
606	else
607		val &= ~MV88E6XXX_PORT_CTL1_MESSAGE_PORT;
608
609	return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL1, val);
610}
611
612/* Offset 0x06: Port Based VLAN Map */
613
614int mv88e6xxx_port_set_vlan_map(struct mv88e6xxx_chip *chip, int port, u16 map)
615{
616	const u16 mask = mv88e6xxx_port_mask(chip);
617	u16 reg;
618	int err;
619
620	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_BASE_VLAN, &reg);
621	if (err)
622		return err;
623
624	reg &= ~mask;
625	reg |= map & mask;
626
627	err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_BASE_VLAN, reg);
628	if (err)
629		return err;
630
631	dev_dbg(chip->dev, "p%d: VLANTable set to %.3x\n", port, map);
632
633	return 0;
634}
635
636int mv88e6xxx_port_get_fid(struct mv88e6xxx_chip *chip, int port, u16 *fid)
637{
638	const u16 upper_mask = (mv88e6xxx_num_databases(chip) - 1) >> 4;
639	u16 reg;
640	int err;
641
642	/* Port's default FID lower 4 bits are located in reg 0x06, offset 12 */
643	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_BASE_VLAN, &reg);
644	if (err)
645		return err;
646
647	*fid = (reg & 0xf000) >> 12;
648
649	/* Port's default FID upper bits are located in reg 0x05, offset 0 */
650	if (upper_mask) {
651		err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL1,
652					  &reg);
653		if (err)
654			return err;
655
656		*fid |= (reg & upper_mask) << 4;
657	}
658
659	return 0;
660}
661
662int mv88e6xxx_port_set_fid(struct mv88e6xxx_chip *chip, int port, u16 fid)
663{
664	const u16 upper_mask = (mv88e6xxx_num_databases(chip) - 1) >> 4;
665	u16 reg;
666	int err;
667
668	if (fid >= mv88e6xxx_num_databases(chip))
669		return -EINVAL;
670
671	/* Port's default FID lower 4 bits are located in reg 0x06, offset 12 */
672	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_BASE_VLAN, &reg);
673	if (err)
674		return err;
675
676	reg &= 0x0fff;
677	reg |= (fid & 0x000f) << 12;
678
679	err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_BASE_VLAN, reg);
680	if (err)
681		return err;
682
683	/* Port's default FID upper bits are located in reg 0x05, offset 0 */
684	if (upper_mask) {
685		err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL1,
686					  &reg);
687		if (err)
688			return err;
689
690		reg &= ~upper_mask;
691		reg |= (fid >> 4) & upper_mask;
692
693		err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL1,
694					   reg);
695		if (err)
696			return err;
697	}
698
699	dev_dbg(chip->dev, "p%d: FID set to %u\n", port, fid);
700
701	return 0;
702}
703
704/* Offset 0x07: Default Port VLAN ID & Priority */
705
706int mv88e6xxx_port_get_pvid(struct mv88e6xxx_chip *chip, int port, u16 *pvid)
707{
708	u16 reg;
709	int err;
710
711	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_DEFAULT_VLAN,
712				  &reg);
713	if (err)
714		return err;
715
716	*pvid = reg & MV88E6XXX_PORT_DEFAULT_VLAN_MASK;
717
718	return 0;
719}
720
721int mv88e6xxx_port_set_pvid(struct mv88e6xxx_chip *chip, int port, u16 pvid)
722{
723	u16 reg;
724	int err;
725
726	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_DEFAULT_VLAN,
727				  &reg);
728	if (err)
729		return err;
730
731	reg &= ~MV88E6XXX_PORT_DEFAULT_VLAN_MASK;
732	reg |= pvid & MV88E6XXX_PORT_DEFAULT_VLAN_MASK;
733
734	err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_DEFAULT_VLAN,
735				   reg);
736	if (err)
737		return err;
738
739	dev_dbg(chip->dev, "p%d: DefaultVID set to %u\n", port, pvid);
740
741	return 0;
742}
743
744/* Offset 0x08: Port Control 2 Register */
745
746static const char * const mv88e6xxx_port_8021q_mode_names[] = {
747	[MV88E6XXX_PORT_CTL2_8021Q_MODE_DISABLED] = "Disabled",
748	[MV88E6XXX_PORT_CTL2_8021Q_MODE_FALLBACK] = "Fallback",
749	[MV88E6XXX_PORT_CTL2_8021Q_MODE_CHECK] = "Check",
750	[MV88E6XXX_PORT_CTL2_8021Q_MODE_SECURE] = "Secure",
751};
752
753static int mv88e6185_port_set_default_forward(struct mv88e6xxx_chip *chip,
754					      int port, bool multicast)
755{
756	int err;
757	u16 reg;
758
759	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL2, &reg);
760	if (err)
761		return err;
762
763	if (multicast)
764		reg |= MV88E6XXX_PORT_CTL2_DEFAULT_FORWARD;
765	else
766		reg &= ~MV88E6XXX_PORT_CTL2_DEFAULT_FORWARD;
767
768	return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL2, reg);
769}
770
771int mv88e6185_port_set_egress_floods(struct mv88e6xxx_chip *chip, int port,
772				     bool unicast, bool multicast)
773{
774	int err;
775
776	err = mv88e6185_port_set_forward_unknown(chip, port, unicast);
777	if (err)
778		return err;
779
780	return mv88e6185_port_set_default_forward(chip, port, multicast);
781}
782
783int mv88e6095_port_set_upstream_port(struct mv88e6xxx_chip *chip, int port,
784				     int upstream_port)
785{
786	int err;
787	u16 reg;
788
789	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL2, &reg);
790	if (err)
791		return err;
792
793	reg &= ~MV88E6095_PORT_CTL2_CPU_PORT_MASK;
794	reg |= upstream_port;
795
796	return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL2, reg);
797}
798
799int mv88e6xxx_port_set_8021q_mode(struct mv88e6xxx_chip *chip, int port,
800				  u16 mode)
801{
802	u16 reg;
803	int err;
804
805	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL2, &reg);
806	if (err)
807		return err;
808
809	reg &= ~MV88E6XXX_PORT_CTL2_8021Q_MODE_MASK;
810	reg |= mode & MV88E6XXX_PORT_CTL2_8021Q_MODE_MASK;
811
812	err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL2, reg);
813	if (err)
814		return err;
815
816	dev_dbg(chip->dev, "p%d: 802.1QMode set to %s\n", port,
817		mv88e6xxx_port_8021q_mode_names[mode]);
818
819	return 0;
820}
821
822int mv88e6xxx_port_set_map_da(struct mv88e6xxx_chip *chip, int port)
823{
824	u16 reg;
825	int err;
826
827	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL2, &reg);
828	if (err)
829		return err;
830
831	reg |= MV88E6XXX_PORT_CTL2_MAP_DA;
832
833	return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL2, reg);
834}
835
836int mv88e6165_port_set_jumbo_size(struct mv88e6xxx_chip *chip, int port,
837				  size_t size)
838{
839	u16 reg;
840	int err;
841
842	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL2, &reg);
843	if (err)
844		return err;
845
846	reg &= ~MV88E6XXX_PORT_CTL2_JUMBO_MODE_MASK;
847
848	if (size <= 1522)
849		reg |= MV88E6XXX_PORT_CTL2_JUMBO_MODE_1522;
850	else if (size <= 2048)
851		reg |= MV88E6XXX_PORT_CTL2_JUMBO_MODE_2048;
852	else if (size <= 10240)
853		reg |= MV88E6XXX_PORT_CTL2_JUMBO_MODE_10240;
854	else
855		return -ERANGE;
856
857	return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL2, reg);
858}
859
860/* Offset 0x09: Port Rate Control */
861
862int mv88e6095_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port)
863{
864	return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_EGRESS_RATE_CTL1,
865				    0x0000);
866}
867
868int mv88e6097_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port)
869{
870	return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_EGRESS_RATE_CTL1,
871				    0x0001);
872}
873
874/* Offset 0x0C: Port ATU Control */
875
876int mv88e6xxx_port_disable_learn_limit(struct mv88e6xxx_chip *chip, int port)
877{
878	return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_ATU_CTL, 0);
879}
880
881/* Offset 0x0D: (Priority) Override Register */
882
883int mv88e6xxx_port_disable_pri_override(struct mv88e6xxx_chip *chip, int port)
884{
885	return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_PRI_OVERRIDE, 0);
886}
887
888/* Offset 0x0f: Port Ether type */
889
890int mv88e6351_port_set_ether_type(struct mv88e6xxx_chip *chip, int port,
891				  u16 etype)
892{
893	return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_ETH_TYPE, etype);
894}
895
896/* Offset 0x18: Port IEEE Priority Remapping Registers [0-3]
897 * Offset 0x19: Port IEEE Priority Remapping Registers [4-7]
898 */
899
900int mv88e6095_port_tag_remap(struct mv88e6xxx_chip *chip, int port)
901{
902	int err;
903
904	/* Use a direct priority mapping for all IEEE tagged frames */
905	err = mv88e6xxx_port_write(chip, port,
906				   MV88E6095_PORT_IEEE_PRIO_REMAP_0123,
907				   0x3210);
908	if (err)
909		return err;
910
911	return mv88e6xxx_port_write(chip, port,
912				    MV88E6095_PORT_IEEE_PRIO_REMAP_4567,
913				    0x7654);
914}
915
916static int mv88e6xxx_port_ieeepmt_write(struct mv88e6xxx_chip *chip,
917					int port, u16 table, u8 ptr, u16 data)
918{
919	u16 reg;
920
921	reg = MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_UPDATE | table |
922		(ptr << __bf_shf(MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_PTR_MASK)) |
923		(data & MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_DATA_MASK);
924
925	return mv88e6xxx_port_write(chip, port,
926				    MV88E6390_PORT_IEEE_PRIO_MAP_TABLE, reg);
927}
928
929int mv88e6390_port_tag_remap(struct mv88e6xxx_chip *chip, int port)
930{
931	int err, i;
932	u16 table;
933
934	for (i = 0; i <= 7; i++) {
935		table = MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_INGRESS_PCP;
936		err = mv88e6xxx_port_ieeepmt_write(chip, port, table, i,
937						   (i | i << 4));
938		if (err)
939			return err;
940
941		table = MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_GREEN_PCP;
942		err = mv88e6xxx_port_ieeepmt_write(chip, port, table, i, i);
943		if (err)
944			return err;
945
946		table = MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_YELLOW_PCP;
947		err = mv88e6xxx_port_ieeepmt_write(chip, port, table, i, i);
948		if (err)
949			return err;
950
951		table = MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_AVB_PCP;
952		err = mv88e6xxx_port_ieeepmt_write(chip, port, table, i, i);
953		if (err)
954			return err;
955	}
956
957	return 0;
958}