port.c 30.1 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0-or-later
2 3 4 5 6
/*
 * Marvell 88E6xxx Switch Port Registers support
 *
 * Copyright (c) 2008 Marvell Semiconductor
 *
V
Vivien Didelot 已提交
7 8
 * Copyright (c) 2016-2017 Savoir-faire Linux Inc.
 *	Vivien Didelot <vivien.didelot@savoirfairelinux.com>
9 10
 */

11
#include <linux/bitfield.h>
12
#include <linux/if_bridge.h>
13
#include <linux/phy.h>
14
#include <linux/phylink.h>
15 16

#include "chip.h"
17
#include "port.h"
18
#include "serdes.h"
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34

int mv88e6xxx_port_read(struct mv88e6xxx_chip *chip, int port, int reg,
			u16 *val)
{
	int addr = chip->info->port_base_addr + port;

	return mv88e6xxx_read(chip, addr, reg, val);
}

int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg,
			 u16 val)
{
	int addr = chip->info->port_base_addr + port;

	return mv88e6xxx_write(chip, addr, reg, val);
}
35

36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
/* Offset 0x00: MAC (or PCS or Physical) Status Register
 *
 * For most devices, this is read only. However the 6185 has the MyPause
 * bit read/write.
 */
int mv88e6185_port_set_pause(struct mv88e6xxx_chip *chip, int port,
			     int pause)
{
	u16 reg;
	int err;

	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &reg);
	if (err)
		return err;

	if (pause)
		reg |= MV88E6XXX_PORT_STS_MY_PAUSE;
	else
		reg &= ~MV88E6XXX_PORT_STS_MY_PAUSE;

	return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_STS, reg);
}

59 60 61
/* Offset 0x01: MAC (or PCS or Physical) Control Register
 *
 * Link, Duplex and Flow Control have one force bit, one value bit.
62 63 64 65
 *
 * For port's MAC speed, ForceSpd (or SpdValue) bits 1:0 program the value.
 * Alternative values require the 200BASE (or AltSpeed) bit 12 set.
 * Newer chips need a ForcedSpd bit 13 set to consider the value.
66 67
 */

68 69 70 71 72 73
static int mv88e6xxx_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port,
					  phy_interface_t mode)
{
	u16 reg;
	int err;

74
	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_MAC_CTL, &reg);
75 76 77
	if (err)
		return err;

78 79
	reg &= ~(MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_RXCLK |
		 MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_TXCLK);
80 81 82

	switch (mode) {
	case PHY_INTERFACE_MODE_RGMII_RXID:
83
		reg |= MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_RXCLK;
84 85
		break;
	case PHY_INTERFACE_MODE_RGMII_TXID:
86
		reg |= MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_TXCLK;
87 88
		break;
	case PHY_INTERFACE_MODE_RGMII_ID:
89 90
		reg |= MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_RXCLK |
			MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_TXCLK;
91
		break;
92
	case PHY_INTERFACE_MODE_RGMII:
93
		break;
94 95
	default:
		return 0;
96 97
	}

98
	err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_MAC_CTL, reg);
99 100 101
	if (err)
		return err;

102
	dev_dbg(chip->dev, "p%d: delay RXCLK %s, TXCLK %s\n", port,
103 104
		reg & MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_RXCLK ? "yes" : "no",
		reg & MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_TXCLK ? "yes" : "no");
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126

	return 0;
}

int mv88e6352_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port,
				   phy_interface_t mode)
{
	if (port < 5)
		return -EOPNOTSUPP;

	return mv88e6xxx_port_set_rgmii_delay(chip, port, mode);
}

int mv88e6390_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port,
				   phy_interface_t mode)
{
	if (port != 0)
		return -EOPNOTSUPP;

	return mv88e6xxx_port_set_rgmii_delay(chip, port, mode);
}

127 128 129 130 131
int mv88e6xxx_port_set_link(struct mv88e6xxx_chip *chip, int port, int link)
{
	u16 reg;
	int err;

132
	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_MAC_CTL, &reg);
133 134 135
	if (err)
		return err;

136 137
	reg &= ~(MV88E6XXX_PORT_MAC_CTL_FORCE_LINK |
		 MV88E6XXX_PORT_MAC_CTL_LINK_UP);
138 139 140

	switch (link) {
	case LINK_FORCED_DOWN:
141
		reg |= MV88E6XXX_PORT_MAC_CTL_FORCE_LINK;
142 143
		break;
	case LINK_FORCED_UP:
144 145
		reg |= MV88E6XXX_PORT_MAC_CTL_FORCE_LINK |
			MV88E6XXX_PORT_MAC_CTL_LINK_UP;
146 147 148 149 150 151 152 153
		break;
	case LINK_UNFORCED:
		/* normal link detection */
		break;
	default:
		return -EINVAL;
	}

154
	err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_MAC_CTL, reg);
155 156 157
	if (err)
		return err;

158
	dev_dbg(chip->dev, "p%d: %s link %s\n", port,
159 160
		reg & MV88E6XXX_PORT_MAC_CTL_FORCE_LINK ? "Force" : "Unforce",
		reg & MV88E6XXX_PORT_MAC_CTL_LINK_UP ? "up" : "down");
161 162 163 164

	return 0;
}

165 166 167 168 169
int mv88e6xxx_port_set_duplex(struct mv88e6xxx_chip *chip, int port, int dup)
{
	u16 reg;
	int err;

170
	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_MAC_CTL, &reg);
171 172 173
	if (err)
		return err;

174 175
	reg &= ~(MV88E6XXX_PORT_MAC_CTL_FORCE_DUPLEX |
		 MV88E6XXX_PORT_MAC_CTL_DUPLEX_FULL);
176 177 178

	switch (dup) {
	case DUPLEX_HALF:
179
		reg |= MV88E6XXX_PORT_MAC_CTL_FORCE_DUPLEX;
180 181
		break;
	case DUPLEX_FULL:
182 183
		reg |= MV88E6XXX_PORT_MAC_CTL_FORCE_DUPLEX |
			MV88E6XXX_PORT_MAC_CTL_DUPLEX_FULL;
184 185 186 187 188
		break;
	case DUPLEX_UNFORCED:
		/* normal duplex detection */
		break;
	default:
189
		return -EOPNOTSUPP;
190 191
	}

192
	err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_MAC_CTL, reg);
193 194 195
	if (err)
		return err;

196
	dev_dbg(chip->dev, "p%d: %s %s duplex\n", port,
197 198
		reg & MV88E6XXX_PORT_MAC_CTL_FORCE_DUPLEX ? "Force" : "Unforce",
		reg & MV88E6XXX_PORT_MAC_CTL_DUPLEX_FULL ? "full" : "half");
199 200 201 202

	return 0;
}

203 204 205 206 207 208 209 210
static int mv88e6xxx_port_set_speed(struct mv88e6xxx_chip *chip, int port,
				    int speed, bool alt_bit, bool force_bit)
{
	u16 reg, ctrl;
	int err;

	switch (speed) {
	case 10:
211
		ctrl = MV88E6XXX_PORT_MAC_CTL_SPEED_10;
212 213
		break;
	case 100:
214
		ctrl = MV88E6XXX_PORT_MAC_CTL_SPEED_100;
215 216 217
		break;
	case 200:
		if (alt_bit)
218 219
			ctrl = MV88E6XXX_PORT_MAC_CTL_SPEED_100 |
				MV88E6390_PORT_MAC_CTL_ALTSPEED;
220
		else
221
			ctrl = MV88E6065_PORT_MAC_CTL_SPEED_200;
222 223
		break;
	case 1000:
224
		ctrl = MV88E6XXX_PORT_MAC_CTL_SPEED_1000;
225 226
		break;
	case 2500:
227 228 229 230 231
		if (alt_bit)
			ctrl = MV88E6390_PORT_MAC_CTL_SPEED_10000 |
				MV88E6390_PORT_MAC_CTL_ALTSPEED;
		else
			ctrl = MV88E6390_PORT_MAC_CTL_SPEED_10000;
232 233 234 235
		break;
	case 10000:
		/* all bits set, fall through... */
	case SPEED_UNFORCED:
236
		ctrl = MV88E6XXX_PORT_MAC_CTL_SPEED_UNFORCED;
237 238 239 240 241
		break;
	default:
		return -EOPNOTSUPP;
	}

242
	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_MAC_CTL, &reg);
243 244 245
	if (err)
		return err;

246
	reg &= ~MV88E6XXX_PORT_MAC_CTL_SPEED_MASK;
247
	if (alt_bit)
248
		reg &= ~MV88E6390_PORT_MAC_CTL_ALTSPEED;
249
	if (force_bit) {
250
		reg &= ~MV88E6390_PORT_MAC_CTL_FORCE_SPEED;
251
		if (speed != SPEED_UNFORCED)
252
			ctrl |= MV88E6390_PORT_MAC_CTL_FORCE_SPEED;
253 254 255
	}
	reg |= ctrl;

256
	err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_MAC_CTL, reg);
257 258 259 260
	if (err)
		return err;

	if (speed)
261
		dev_dbg(chip->dev, "p%d: Speed set to %d Mbps\n", port, speed);
262
	else
263
		dev_dbg(chip->dev, "p%d: Speed unforced\n", port);
264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292

	return 0;
}

/* Support 10, 100, 200 Mbps (e.g. 88E6065 family) */
int mv88e6065_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
{
	if (speed == SPEED_MAX)
		speed = 200;

	if (speed > 200)
		return -EOPNOTSUPP;

	/* Setting 200 Mbps on port 0 to 3 selects 100 Mbps */
	return mv88e6xxx_port_set_speed(chip, port, speed, false, false);
}

/* Support 10, 100, 1000 Mbps (e.g. 88E6185 family) */
int mv88e6185_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
{
	if (speed == SPEED_MAX)
		speed = 1000;

	if (speed == 200 || speed > 1000)
		return -EOPNOTSUPP;

	return mv88e6xxx_port_set_speed(chip, port, speed, false, false);
}

293 294 295 296 297 298 299 300 301 302 303 304
/* Support 10, 100 Mbps (e.g. 88E6250 family) */
int mv88e6250_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
{
	if (speed == SPEED_MAX)
		speed = 100;

	if (speed > 100)
		return -EOPNOTSUPP;

	return mv88e6xxx_port_set_speed(chip, port, speed, false, false);
}

305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322
/* Support 10, 100, 200, 1000, 2500 Mbps (e.g. 88E6341) */
int mv88e6341_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
{
	if (speed == SPEED_MAX)
		speed = port < 5 ? 1000 : 2500;

	if (speed > 2500)
		return -EOPNOTSUPP;

	if (speed == 200 && port != 0)
		return -EOPNOTSUPP;

	if (speed == 2500 && port < 5)
		return -EOPNOTSUPP;

	return mv88e6xxx_port_set_speed(chip, port, speed, !port, true);
}

323 324 325 326 327 328 329 330
phy_interface_t mv88e6341_port_max_speed_mode(int port)
{
	if (port == 5)
		return PHY_INTERFACE_MODE_2500BASEX;

	return PHY_INTERFACE_MODE_NA;
}

331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363
/* Support 10, 100, 200, 1000 Mbps (e.g. 88E6352 family) */
int mv88e6352_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
{
	if (speed == SPEED_MAX)
		speed = 1000;

	if (speed > 1000)
		return -EOPNOTSUPP;

	if (speed == 200 && port < 5)
		return -EOPNOTSUPP;

	return mv88e6xxx_port_set_speed(chip, port, speed, true, false);
}

/* Support 10, 100, 200, 1000, 2500 Mbps (e.g. 88E6390) */
int mv88e6390_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
{
	if (speed == SPEED_MAX)
		speed = port < 9 ? 1000 : 2500;

	if (speed > 2500)
		return -EOPNOTSUPP;

	if (speed == 200 && port != 0)
		return -EOPNOTSUPP;

	if (speed == 2500 && port < 9)
		return -EOPNOTSUPP;

	return mv88e6xxx_port_set_speed(chip, port, speed, true, true);
}

364 365 366 367 368 369 370 371
phy_interface_t mv88e6390_port_max_speed_mode(int port)
{
	if (port == 9 || port == 10)
		return PHY_INTERFACE_MODE_2500BASEX;

	return PHY_INTERFACE_MODE_NA;
}

372 373 374 375 376 377 378 379 380 381 382 383 384 385 386
/* Support 10, 100, 200, 1000, 2500, 10000 Mbps (e.g. 88E6190X) */
int mv88e6390x_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
{
	if (speed == SPEED_MAX)
		speed = port < 9 ? 1000 : 10000;

	if (speed == 200 && port != 0)
		return -EOPNOTSUPP;

	if (speed >= 2500 && port < 9)
		return -EOPNOTSUPP;

	return mv88e6xxx_port_set_speed(chip, port, speed, true, true);
}

387 388 389 390 391 392 393 394
phy_interface_t mv88e6390x_port_max_speed_mode(int port)
{
	if (port == 9 || port == 10)
		return PHY_INTERFACE_MODE_XAUI;

	return PHY_INTERFACE_MODE_NA;
}

395 396 397
int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
			      phy_interface_t mode)
{
398
	u8 lane;
399
	u16 cmode;
400
	u16 reg;
401 402 403 404 405
	int err;

	if (port != 9 && port != 10)
		return -EOPNOTSUPP;

406 407 408 409 410 411
	/* Default to a slow mode, so freeing up SERDES interfaces for
	 * other ports which might use them for SFPs.
	 */
	if (mode == PHY_INTERFACE_MODE_NA)
		mode = PHY_INTERFACE_MODE_1000BASEX;

412 413
	switch (mode) {
	case PHY_INTERFACE_MODE_1000BASEX:
414
		cmode = MV88E6XXX_PORT_STS_CMODE_1000BASEX;
415 416
		break;
	case PHY_INTERFACE_MODE_SGMII:
417
		cmode = MV88E6XXX_PORT_STS_CMODE_SGMII;
418 419
		break;
	case PHY_INTERFACE_MODE_2500BASEX:
420
		cmode = MV88E6XXX_PORT_STS_CMODE_2500BASEX;
421 422
		break;
	case PHY_INTERFACE_MODE_XGMII:
423
	case PHY_INTERFACE_MODE_XAUI:
424
		cmode = MV88E6XXX_PORT_STS_CMODE_XAUI;
425 426
		break;
	case PHY_INTERFACE_MODE_RXAUI:
427
		cmode = MV88E6XXX_PORT_STS_CMODE_RXAUI;
428 429 430 431 432
		break;
	default:
		cmode = 0;
	}

433 434 435 436
	/* cmode doesn't change, nothing to do for us */
	if (cmode == chip->ports[port].cmode)
		return 0;

437 438 439
	err = mv88e6xxx_serdes_get_lane(chip, port, &lane);
	if (err && err != -ENODEV)
		return err;
440

441
	if (err != -ENODEV) {
442 443 444 445 446 447
		if (chip->ports[port].serdes_irq) {
			err = mv88e6390_serdes_irq_disable(chip, port, lane);
			if (err)
				return err;
		}

448
		err = mv88e6390_serdes_power(chip, port, false);
449 450 451 452
		if (err)
			return err;
	}

453
	chip->ports[port].cmode = 0;
454

455
	if (cmode) {
456
		err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &reg);
457 458 459
		if (err)
			return err;

460
		reg &= ~MV88E6XXX_PORT_STS_CMODE_MASK;
461 462
		reg |= cmode;

463
		err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_STS, reg);
464 465
		if (err)
			return err;
466

467 468
		chip->ports[port].cmode = cmode;

469 470 471
		err = mv88e6xxx_serdes_get_lane(chip, port, &lane);
		if (err)
			return err;
472

473
		err = mv88e6390_serdes_power(chip, port, true);
474 475
		if (err)
			return err;
476 477 478 479 480 481

		if (chip->ports[port].serdes_irq) {
			err = mv88e6390_serdes_irq_enable(chip, port, lane);
			if (err)
				return err;
		}
482 483 484 485 486
	}

	return 0;
}

487 488 489 490
int mv88e6390_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
			     phy_interface_t mode)
{
	switch (mode) {
491 492
	case PHY_INTERFACE_MODE_NA:
		return 0;
493 494 495 496 497 498 499 500 501 502 503
	case PHY_INTERFACE_MODE_XGMII:
	case PHY_INTERFACE_MODE_XAUI:
	case PHY_INTERFACE_MODE_RXAUI:
		return -EINVAL;
	default:
		break;
	}

	return mv88e6390x_port_set_cmode(chip, port, mode);
}

504
int mv88e6185_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode)
505 506 507 508 509 510 511 512
{
	int err;
	u16 reg;

	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &reg);
	if (err)
		return err;

513 514 515
	*cmode = reg & MV88E6185_PORT_STS_CMODE_MASK;

	return 0;
516 517
}

518
int mv88e6352_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode)
519 520 521 522
{
	int err;
	u16 reg;

523
	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &reg);
524 525 526
	if (err)
		return err;

527
	*cmode = reg & MV88E6XXX_PORT_STS_CMODE_MASK;
528 529 530 531

	return 0;
}

532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592
int mv88e6250_port_link_state(struct mv88e6xxx_chip *chip, int port,
			      struct phylink_link_state *state)
{
	int err;
	u16 reg;

	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &reg);
	if (err)
		return err;

	if (port < 5) {
		switch (reg & MV88E6250_PORT_STS_PORTMODE_MASK) {
		case MV88E6250_PORT_STS_PORTMODE_PHY_10_HALF:
			state->speed = SPEED_10;
			state->duplex = DUPLEX_HALF;
			break;
		case MV88E6250_PORT_STS_PORTMODE_PHY_100_HALF:
			state->speed = SPEED_100;
			state->duplex = DUPLEX_HALF;
			break;
		case MV88E6250_PORT_STS_PORTMODE_PHY_10_FULL:
			state->speed = SPEED_10;
			state->duplex = DUPLEX_FULL;
			break;
		case MV88E6250_PORT_STS_PORTMODE_PHY_100_FULL:
			state->speed = SPEED_100;
			state->duplex = DUPLEX_FULL;
			break;
		default:
			state->speed = SPEED_UNKNOWN;
			state->duplex = DUPLEX_UNKNOWN;
			break;
		}
	} else {
		switch (reg & MV88E6250_PORT_STS_PORTMODE_MASK) {
		case MV88E6250_PORT_STS_PORTMODE_MII_10_HALF:
			state->speed = SPEED_10;
			state->duplex = DUPLEX_HALF;
			break;
		case MV88E6250_PORT_STS_PORTMODE_MII_100_HALF:
			state->speed = SPEED_100;
			state->duplex = DUPLEX_HALF;
			break;
		case MV88E6250_PORT_STS_PORTMODE_MII_10_FULL:
			state->speed = SPEED_10;
			state->duplex = DUPLEX_FULL;
			break;
		case MV88E6250_PORT_STS_PORTMODE_MII_100_FULL:
			state->speed = SPEED_100;
			state->duplex = DUPLEX_FULL;
			break;
		default:
			state->speed = SPEED_UNKNOWN;
			state->duplex = DUPLEX_UNKNOWN;
			break;
		}
	}

	state->link = !!(reg & MV88E6250_PORT_STS_LINK);
	state->an_enabled = 1;
	state->an_complete = state->link;
593
	state->interface = PHY_INTERFACE_MODE_NA;
594 595 596 597

	return 0;
}

598
int mv88e6352_port_link_state(struct mv88e6xxx_chip *chip, int port,
599 600 601 602 603
			      struct phylink_link_state *state)
{
	int err;
	u16 reg;

604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620
	switch (chip->ports[port].cmode) {
	case MV88E6XXX_PORT_STS_CMODE_RGMII:
		err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_MAC_CTL,
					  &reg);
		if (err)
			return err;

		if ((reg & MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_RXCLK) &&
		    (reg & MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_TXCLK))
			state->interface = PHY_INTERFACE_MODE_RGMII_ID;
		else if (reg & MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_RXCLK)
			state->interface = PHY_INTERFACE_MODE_RGMII_RXID;
		else if (reg & MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_TXCLK)
			state->interface = PHY_INTERFACE_MODE_RGMII_TXID;
		else
			state->interface = PHY_INTERFACE_MODE_RGMII;
		break;
621
	case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640
		state->interface = PHY_INTERFACE_MODE_1000BASEX;
		break;
	case MV88E6XXX_PORT_STS_CMODE_SGMII:
		state->interface = PHY_INTERFACE_MODE_SGMII;
		break;
	case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
		state->interface = PHY_INTERFACE_MODE_2500BASEX;
		break;
	case MV88E6XXX_PORT_STS_CMODE_XAUI:
		state->interface = PHY_INTERFACE_MODE_XAUI;
		break;
	case MV88E6XXX_PORT_STS_CMODE_RXAUI:
		state->interface = PHY_INTERFACE_MODE_RXAUI;
		break;
	default:
		/* we do not support other cmode values here */
		state->interface = PHY_INTERFACE_MODE_NA;
	}

641 642 643 644 645 646 647 648 649 650 651 652 653 654 655
	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &reg);
	if (err)
		return err;

	switch (reg & MV88E6XXX_PORT_STS_SPEED_MASK) {
	case MV88E6XXX_PORT_STS_SPEED_10:
		state->speed = SPEED_10;
		break;
	case MV88E6XXX_PORT_STS_SPEED_100:
		state->speed = SPEED_100;
		break;
	case MV88E6XXX_PORT_STS_SPEED_1000:
		state->speed = SPEED_1000;
		break;
	case MV88E6XXX_PORT_STS_SPEED_10000:
656
		if ((reg & MV88E6XXX_PORT_STS_CMODE_MASK) ==
657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672
		    MV88E6XXX_PORT_STS_CMODE_2500BASEX)
			state->speed = SPEED_2500;
		else
			state->speed = SPEED_10000;
		break;
	}

	state->duplex = reg & MV88E6XXX_PORT_STS_DUPLEX ?
			DUPLEX_FULL : DUPLEX_HALF;
	state->link = !!(reg & MV88E6XXX_PORT_STS_LINK);
	state->an_enabled = 1;
	state->an_complete = state->link;

	return 0;
}

673 674 675 676
int mv88e6185_port_link_state(struct mv88e6xxx_chip *chip, int port,
			      struct phylink_link_state *state)
{
	if (state->interface == PHY_INTERFACE_MODE_1000BASEX) {
677
		u8 cmode = chip->ports[port].cmode;
678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708

		/* When a port is in "Cross-chip serdes" mode, it uses
		 * 1000Base-X full duplex mode, but there is no automatic
		 * link detection. Use the sync OK status for link (as it
		 * would do for 1000Base-X mode.)
		 */
		if (cmode == MV88E6185_PORT_STS_CMODE_SERDES) {
			u16 mac;
			int err;

			err = mv88e6xxx_port_read(chip, port,
						  MV88E6XXX_PORT_MAC_CTL, &mac);
			if (err)
				return err;

			state->link = !!(mac & MV88E6185_PORT_MAC_CTL_SYNC_OK);
			state->an_enabled = 1;
			state->an_complete =
				!!(mac & MV88E6185_PORT_MAC_CTL_AN_DONE);
			state->duplex =
				state->link ? DUPLEX_FULL : DUPLEX_UNKNOWN;
			state->speed =
				state->link ? SPEED_1000 : SPEED_UNKNOWN;

			return 0;
		}
	}

	return mv88e6352_port_link_state(chip, port, state);
}

709
/* Offset 0x02: Jamming Control
710 711 712 713 714
 *
 * Do not limit the period of time that this port can be paused for by
 * the remote end or the period of time that this port can pause the
 * remote end.
 */
715 716
int mv88e6097_port_pause_limit(struct mv88e6xxx_chip *chip, int port, u8 in,
			       u8 out)
717
{
718 719
	return mv88e6xxx_port_write(chip, port, MV88E6097_PORT_JAM_CTL,
				    out << 8 | in);
720 721
}

722 723
int mv88e6390_port_pause_limit(struct mv88e6xxx_chip *chip, int port, u8 in,
			       u8 out)
724 725 726
{
	int err;

727 728 729
	err = mv88e6xxx_port_write(chip, port, MV88E6390_PORT_FLOW_CTL,
				   MV88E6390_PORT_FLOW_CTL_UPDATE |
				   MV88E6390_PORT_FLOW_CTL_LIMIT_IN | in);
730 731 732
	if (err)
		return err;

733 734 735
	return mv88e6xxx_port_write(chip, port, MV88E6390_PORT_FLOW_CTL,
				    MV88E6390_PORT_FLOW_CTL_UPDATE |
				    MV88E6390_PORT_FLOW_CTL_LIMIT_OUT | out);
736 737
}

738 739 740
/* Offset 0x04: Port Control Register */

static const char * const mv88e6xxx_port_state_names[] = {
741 742 743 744
	[MV88E6XXX_PORT_CTL0_STATE_DISABLED] = "Disabled",
	[MV88E6XXX_PORT_CTL0_STATE_BLOCKING] = "Blocking/Listening",
	[MV88E6XXX_PORT_CTL0_STATE_LEARNING] = "Learning",
	[MV88E6XXX_PORT_CTL0_STATE_FORWARDING] = "Forwarding",
745 746 747 748 749 750 751
};

int mv88e6xxx_port_set_state(struct mv88e6xxx_chip *chip, int port, u8 state)
{
	u16 reg;
	int err;

752
	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL0, &reg);
753 754 755
	if (err)
		return err;

756
	reg &= ~MV88E6XXX_PORT_CTL0_STATE_MASK;
757 758 759

	switch (state) {
	case BR_STATE_DISABLED:
760
		state = MV88E6XXX_PORT_CTL0_STATE_DISABLED;
761 762 763
		break;
	case BR_STATE_BLOCKING:
	case BR_STATE_LISTENING:
764
		state = MV88E6XXX_PORT_CTL0_STATE_BLOCKING;
765 766
		break;
	case BR_STATE_LEARNING:
767
		state = MV88E6XXX_PORT_CTL0_STATE_LEARNING;
768 769
		break;
	case BR_STATE_FORWARDING:
770
		state = MV88E6XXX_PORT_CTL0_STATE_FORWARDING;
771 772 773 774 775
		break;
	default:
		return -EINVAL;
	}

776 777
	reg |= state;

778
	err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
779 780 781
	if (err)
		return err;

782 783
	dev_dbg(chip->dev, "p%d: PortState set to %s\n", port,
		mv88e6xxx_port_state_names[state]);
784 785 786

	return 0;
}
787

788
int mv88e6xxx_port_set_egress_mode(struct mv88e6xxx_chip *chip, int port,
789
				   enum mv88e6xxx_egress_mode mode)
790 791 792 793
{
	int err;
	u16 reg;

794
	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL0, &reg);
795 796 797
	if (err)
		return err;

798
	reg &= ~MV88E6XXX_PORT_CTL0_EGRESS_MODE_MASK;
799 800 801

	switch (mode) {
	case MV88E6XXX_EGRESS_MODE_UNMODIFIED:
802
		reg |= MV88E6XXX_PORT_CTL0_EGRESS_MODE_UNMODIFIED;
803 804
		break;
	case MV88E6XXX_EGRESS_MODE_UNTAGGED:
805
		reg |= MV88E6XXX_PORT_CTL0_EGRESS_MODE_UNTAGGED;
806 807
		break;
	case MV88E6XXX_EGRESS_MODE_TAGGED:
808
		reg |= MV88E6XXX_PORT_CTL0_EGRESS_MODE_TAGGED;
809 810
		break;
	case MV88E6XXX_EGRESS_MODE_ETHERTYPE:
811
		reg |= MV88E6XXX_PORT_CTL0_EGRESS_MODE_ETHER_TYPE_DSA;
812 813 814 815
		break;
	default:
		return -EINVAL;
	}
816

817
	return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
818 819 820 821 822 823 824 825
}

int mv88e6085_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port,
				  enum mv88e6xxx_frame_mode mode)
{
	int err;
	u16 reg;

826
	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL0, &reg);
827 828 829
	if (err)
		return err;

830
	reg &= ~MV88E6XXX_PORT_CTL0_FRAME_MODE_MASK;
831 832 833

	switch (mode) {
	case MV88E6XXX_FRAME_MODE_NORMAL:
834
		reg |= MV88E6XXX_PORT_CTL0_FRAME_MODE_NORMAL;
835 836
		break;
	case MV88E6XXX_FRAME_MODE_DSA:
837
		reg |= MV88E6XXX_PORT_CTL0_FRAME_MODE_DSA;
838 839 840 841 842
		break;
	default:
		return -EINVAL;
	}

843
	return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
844 845 846 847 848 849 850 851
}

int mv88e6351_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port,
				  enum mv88e6xxx_frame_mode mode)
{
	int err;
	u16 reg;

852
	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL0, &reg);
853 854 855
	if (err)
		return err;

856
	reg &= ~MV88E6XXX_PORT_CTL0_FRAME_MODE_MASK;
857 858 859

	switch (mode) {
	case MV88E6XXX_FRAME_MODE_NORMAL:
860
		reg |= MV88E6XXX_PORT_CTL0_FRAME_MODE_NORMAL;
861 862
		break;
	case MV88E6XXX_FRAME_MODE_DSA:
863
		reg |= MV88E6XXX_PORT_CTL0_FRAME_MODE_DSA;
864 865
		break;
	case MV88E6XXX_FRAME_MODE_PROVIDER:
866
		reg |= MV88E6XXX_PORT_CTL0_FRAME_MODE_PROVIDER;
867 868
		break;
	case MV88E6XXX_FRAME_MODE_ETHERTYPE:
869
		reg |= MV88E6XXX_PORT_CTL0_FRAME_MODE_ETHER_TYPE_DSA;
870 871 872 873 874
		break;
	default:
		return -EINVAL;
	}

875
	return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
876 877
}

878 879
static int mv88e6185_port_set_forward_unknown(struct mv88e6xxx_chip *chip,
					      int port, bool unicast)
880 881 882 883
{
	int err;
	u16 reg;

884
	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL0, &reg);
885 886 887
	if (err)
		return err;

888
	if (unicast)
889
		reg |= MV88E6185_PORT_CTL0_FORWARD_UNKNOWN;
890
	else
891
		reg &= ~MV88E6185_PORT_CTL0_FORWARD_UNKNOWN;
892

893
	return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
894 895
}

896 897
int mv88e6352_port_set_egress_floods(struct mv88e6xxx_chip *chip, int port,
				     bool unicast, bool multicast)
898 899 900 901
{
	int err;
	u16 reg;

902
	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL0, &reg);
903 904 905
	if (err)
		return err;

906
	reg &= ~MV88E6352_PORT_CTL0_EGRESS_FLOODS_MASK;
907 908

	if (unicast && multicast)
909
		reg |= MV88E6352_PORT_CTL0_EGRESS_FLOODS_ALL_UNKNOWN_DA;
910
	else if (unicast)
911
		reg |= MV88E6352_PORT_CTL0_EGRESS_FLOODS_NO_UNKNOWN_MC_DA;
912
	else if (multicast)
913
		reg |= MV88E6352_PORT_CTL0_EGRESS_FLOODS_NO_UNKNOWN_UC_DA;
914
	else
915
		reg |= MV88E6352_PORT_CTL0_EGRESS_FLOODS_NO_UNKNOWN_DA;
916

917
	return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
918 919
}

920 921
/* Offset 0x05: Port Control 1 */

922 923 924 925 926 927
int mv88e6xxx_port_set_message_port(struct mv88e6xxx_chip *chip, int port,
				    bool message_port)
{
	u16 val;
	int err;

928
	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL1, &val);
929 930 931 932
	if (err)
		return err;

	if (message_port)
933
		val |= MV88E6XXX_PORT_CTL1_MESSAGE_PORT;
934
	else
935
		val &= ~MV88E6XXX_PORT_CTL1_MESSAGE_PORT;
936

937
	return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL1, val);
938 939
}

940 941 942 943
/* Offset 0x06: Port Based VLAN Map */

int mv88e6xxx_port_set_vlan_map(struct mv88e6xxx_chip *chip, int port, u16 map)
{
944
	const u16 mask = mv88e6xxx_port_mask(chip);
945 946 947
	u16 reg;
	int err;

948
	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_BASE_VLAN, &reg);
949 950 951 952 953 954
	if (err)
		return err;

	reg &= ~mask;
	reg |= map & mask;

955
	err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_BASE_VLAN, reg);
956 957 958
	if (err)
		return err;

959
	dev_dbg(chip->dev, "p%d: VLANTable set to %.3x\n", port, map);
960 961 962

	return 0;
}
963 964 965 966 967 968 969 970

int mv88e6xxx_port_get_fid(struct mv88e6xxx_chip *chip, int port, u16 *fid)
{
	const u16 upper_mask = (mv88e6xxx_num_databases(chip) - 1) >> 4;
	u16 reg;
	int err;

	/* Port's default FID lower 4 bits are located in reg 0x06, offset 12 */
971
	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_BASE_VLAN, &reg);
972 973 974 975 976 977 978
	if (err)
		return err;

	*fid = (reg & 0xf000) >> 12;

	/* Port's default FID upper bits are located in reg 0x05, offset 0 */
	if (upper_mask) {
979 980
		err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL1,
					  &reg);
981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999
		if (err)
			return err;

		*fid |= (reg & upper_mask) << 4;
	}

	return 0;
}

int mv88e6xxx_port_set_fid(struct mv88e6xxx_chip *chip, int port, u16 fid)
{
	const u16 upper_mask = (mv88e6xxx_num_databases(chip) - 1) >> 4;
	u16 reg;
	int err;

	if (fid >= mv88e6xxx_num_databases(chip))
		return -EINVAL;

	/* Port's default FID lower 4 bits are located in reg 0x06, offset 12 */
1000
	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_BASE_VLAN, &reg);
1001 1002 1003 1004 1005 1006
	if (err)
		return err;

	reg &= 0x0fff;
	reg |= (fid & 0x000f) << 12;

1007
	err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_BASE_VLAN, reg);
1008 1009 1010 1011 1012
	if (err)
		return err;

	/* Port's default FID upper bits are located in reg 0x05, offset 0 */
	if (upper_mask) {
1013 1014
		err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL1,
					  &reg);
1015 1016 1017 1018 1019 1020
		if (err)
			return err;

		reg &= ~upper_mask;
		reg |= (fid >> 4) & upper_mask;

1021 1022
		err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL1,
					   reg);
1023 1024 1025 1026
		if (err)
			return err;
	}

1027
	dev_dbg(chip->dev, "p%d: FID set to %u\n", port, fid);
1028 1029 1030

	return 0;
}
1031 1032 1033 1034 1035 1036 1037 1038

/* Offset 0x07: Default Port VLAN ID & Priority */

int mv88e6xxx_port_get_pvid(struct mv88e6xxx_chip *chip, int port, u16 *pvid)
{
	u16 reg;
	int err;

1039 1040
	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_DEFAULT_VLAN,
				  &reg);
1041 1042 1043
	if (err)
		return err;

1044
	*pvid = reg & MV88E6XXX_PORT_DEFAULT_VLAN_MASK;
1045 1046 1047 1048 1049 1050 1051 1052 1053

	return 0;
}

int mv88e6xxx_port_set_pvid(struct mv88e6xxx_chip *chip, int port, u16 pvid)
{
	u16 reg;
	int err;

1054 1055
	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_DEFAULT_VLAN,
				  &reg);
1056 1057 1058
	if (err)
		return err;

1059 1060
	reg &= ~MV88E6XXX_PORT_DEFAULT_VLAN_MASK;
	reg |= pvid & MV88E6XXX_PORT_DEFAULT_VLAN_MASK;
1061

1062 1063
	err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_DEFAULT_VLAN,
				   reg);
1064 1065 1066
	if (err)
		return err;

1067
	dev_dbg(chip->dev, "p%d: DefaultVID set to %u\n", port, pvid);
1068 1069 1070

	return 0;
}
1071 1072 1073 1074

/* Offset 0x08: Port Control 2 Register */

static const char * const mv88e6xxx_port_8021q_mode_names[] = {
1075 1076 1077 1078
	[MV88E6XXX_PORT_CTL2_8021Q_MODE_DISABLED] = "Disabled",
	[MV88E6XXX_PORT_CTL2_8021Q_MODE_FALLBACK] = "Fallback",
	[MV88E6XXX_PORT_CTL2_8021Q_MODE_CHECK] = "Check",
	[MV88E6XXX_PORT_CTL2_8021Q_MODE_SECURE] = "Secure",
1079 1080
};

1081 1082
static int mv88e6185_port_set_default_forward(struct mv88e6xxx_chip *chip,
					      int port, bool multicast)
1083 1084 1085 1086
{
	int err;
	u16 reg;

1087
	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL2, &reg);
1088 1089 1090
	if (err)
		return err;

1091
	if (multicast)
1092
		reg |= MV88E6XXX_PORT_CTL2_DEFAULT_FORWARD;
1093
	else
1094
		reg &= ~MV88E6XXX_PORT_CTL2_DEFAULT_FORWARD;
1095

1096
	return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL2, reg);
1097 1098
}

1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110
int mv88e6185_port_set_egress_floods(struct mv88e6xxx_chip *chip, int port,
				     bool unicast, bool multicast)
{
	int err;

	err = mv88e6185_port_set_forward_unknown(chip, port, unicast);
	if (err)
		return err;

	return mv88e6185_port_set_default_forward(chip, port, multicast);
}

1111 1112 1113 1114 1115 1116
int mv88e6095_port_set_upstream_port(struct mv88e6xxx_chip *chip, int port,
				     int upstream_port)
{
	int err;
	u16 reg;

1117
	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL2, &reg);
1118 1119 1120
	if (err)
		return err;

1121
	reg &= ~MV88E6095_PORT_CTL2_CPU_PORT_MASK;
1122 1123
	reg |= upstream_port;

1124
	return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL2, reg);
1125 1126
}

1127 1128 1129 1130 1131 1132
int mv88e6xxx_port_set_8021q_mode(struct mv88e6xxx_chip *chip, int port,
				  u16 mode)
{
	u16 reg;
	int err;

1133
	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL2, &reg);
1134 1135 1136
	if (err)
		return err;

1137 1138
	reg &= ~MV88E6XXX_PORT_CTL2_8021Q_MODE_MASK;
	reg |= mode & MV88E6XXX_PORT_CTL2_8021Q_MODE_MASK;
1139

1140
	err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL2, reg);
1141 1142 1143
	if (err)
		return err;

1144 1145
	dev_dbg(chip->dev, "p%d: 802.1QMode set to %s\n", port,
		mv88e6xxx_port_8021q_mode_names[mode]);
1146 1147 1148

	return 0;
}
1149

1150 1151 1152 1153 1154
int mv88e6xxx_port_set_map_da(struct mv88e6xxx_chip *chip, int port)
{
	u16 reg;
	int err;

1155
	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL2, &reg);
1156 1157 1158
	if (err)
		return err;

1159
	reg |= MV88E6XXX_PORT_CTL2_MAP_DA;
1160

1161
	return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL2, reg);
1162 1163
}

1164 1165
int mv88e6165_port_set_jumbo_size(struct mv88e6xxx_chip *chip, int port,
				  size_t size)
1166 1167 1168 1169
{
	u16 reg;
	int err;

1170
	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL2, &reg);
1171 1172 1173
	if (err)
		return err;

1174
	reg &= ~MV88E6XXX_PORT_CTL2_JUMBO_MODE_MASK;
1175 1176

	if (size <= 1522)
1177
		reg |= MV88E6XXX_PORT_CTL2_JUMBO_MODE_1522;
1178
	else if (size <= 2048)
1179
		reg |= MV88E6XXX_PORT_CTL2_JUMBO_MODE_2048;
1180
	else if (size <= 10240)
1181
		reg |= MV88E6XXX_PORT_CTL2_JUMBO_MODE_10240;
1182 1183
	else
		return -ERANGE;
1184

1185
	return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL2, reg);
1186 1187
}

1188 1189 1190 1191
/* Offset 0x09: Port Rate Control */

int mv88e6095_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port)
{
1192 1193
	return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_EGRESS_RATE_CTL1,
				    0x0000);
1194 1195 1196 1197
}

int mv88e6097_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port)
{
1198 1199
	return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_EGRESS_RATE_CTL1,
				    0x0001);
1200 1201
}

1202 1203 1204 1205
/* Offset 0x0C: Port ATU Control */

int mv88e6xxx_port_disable_learn_limit(struct mv88e6xxx_chip *chip, int port)
{
1206
	return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_ATU_CTL, 0);
1207 1208
}

1209 1210 1211 1212
/* Offset 0x0D: (Priority) Override Register */

int mv88e6xxx_port_disable_pri_override(struct mv88e6xxx_chip *chip, int port)
{
1213
	return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_PRI_OVERRIDE, 0);
1214 1215
}

1216 1217 1218 1219 1220
/* Offset 0x0f: Port Ether type */

int mv88e6351_port_set_ether_type(struct mv88e6xxx_chip *chip, int port,
				  u16 etype)
{
1221
	return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_ETH_TYPE, etype);
1222 1223
}

1224 1225 1226 1227 1228 1229 1230 1231 1232
/* Offset 0x18: Port IEEE Priority Remapping Registers [0-3]
 * Offset 0x19: Port IEEE Priority Remapping Registers [4-7]
 */

int mv88e6095_port_tag_remap(struct mv88e6xxx_chip *chip, int port)
{
	int err;

	/* Use a direct priority mapping for all IEEE tagged frames */
1233 1234 1235
	err = mv88e6xxx_port_write(chip, port,
				   MV88E6095_PORT_IEEE_PRIO_REMAP_0123,
				   0x3210);
1236 1237 1238
	if (err)
		return err;

1239 1240 1241
	return mv88e6xxx_port_write(chip, port,
				    MV88E6095_PORT_IEEE_PRIO_REMAP_4567,
				    0x7654);
1242 1243 1244
}

static int mv88e6xxx_port_ieeepmt_write(struct mv88e6xxx_chip *chip,
1245
					int port, u16 table, u8 ptr, u16 data)
1246 1247 1248
{
	u16 reg;

1249 1250 1251
	reg = MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_UPDATE | table |
		(ptr << __bf_shf(MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_PTR_MASK)) |
		(data & MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_DATA_MASK);
1252

1253 1254
	return mv88e6xxx_port_write(chip, port,
				    MV88E6390_PORT_IEEE_PRIO_MAP_TABLE, reg);
1255 1256 1257 1258 1259
}

int mv88e6390_port_tag_remap(struct mv88e6xxx_chip *chip, int port)
{
	int err, i;
1260
	u16 table;
1261 1262

	for (i = 0; i <= 7; i++) {
1263 1264 1265
		table = MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_INGRESS_PCP;
		err = mv88e6xxx_port_ieeepmt_write(chip, port, table, i,
						   (i | i << 4));
1266 1267 1268
		if (err)
			return err;

1269 1270
		table = MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_GREEN_PCP;
		err = mv88e6xxx_port_ieeepmt_write(chip, port, table, i, i);
1271 1272 1273
		if (err)
			return err;

1274 1275
		table = MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_YELLOW_PCP;
		err = mv88e6xxx_port_ieeepmt_write(chip, port, table, i, i);
1276 1277 1278
		if (err)
			return err;

1279 1280
		table = MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_AVB_PCP;
		err = mv88e6xxx_port_ieeepmt_write(chip, port, table, i, i);
1281 1282 1283 1284 1285 1286
		if (err)
			return err;
	}

	return 0;
}