1 /* 2 * Marvell 88E6xxx Switch Port Registers support 3 * 4 * Copyright (c) 2008 Marvell Semiconductor 5 * 6 * Copyright (c) 2016 Vivien Didelot <vivien.didelot@savoirfairelinux.com> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 */ 13 14 #include "mv88e6xxx.h" 15 #include "port.h" 16 17 int mv88e6xxx_port_read(struct mv88e6xxx_chip *chip, int port, int reg, 18 u16 *val) 19 { 20 int addr = chip->info->port_base_addr + port; 21 22 return mv88e6xxx_read(chip, addr, reg, val); 23 } 24 25 int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg, 26 u16 val) 27 { 28 int addr = chip->info->port_base_addr + port; 29 30 return mv88e6xxx_write(chip, addr, reg, val); 31 } 32 33 /* Offset 0x01: MAC (or PCS or Physical) Control Register 34 * 35 * Link, Duplex and Flow Control have one force bit, one value bit. 36 * 37 * For port's MAC speed, ForceSpd (or SpdValue) bits 1:0 program the value. 38 * Alternative values require the 200BASE (or AltSpeed) bit 12 set. 39 * Newer chips need a ForcedSpd bit 13 set to consider the value. 40 */ 41 42 static int mv88e6xxx_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port, 43 phy_interface_t mode) 44 { 45 u16 reg; 46 int err; 47 48 err = mv88e6xxx_port_read(chip, port, PORT_PCS_CTRL, ®); 49 if (err) 50 return err; 51 52 reg &= ~(PORT_PCS_CTRL_RGMII_DELAY_RXCLK | 53 PORT_PCS_CTRL_RGMII_DELAY_TXCLK); 54 55 switch (mode) { 56 case PHY_INTERFACE_MODE_RGMII_RXID: 57 reg |= PORT_PCS_CTRL_RGMII_DELAY_RXCLK; 58 break; 59 case PHY_INTERFACE_MODE_RGMII_TXID: 60 reg |= PORT_PCS_CTRL_RGMII_DELAY_TXCLK; 61 break; 62 case PHY_INTERFACE_MODE_RGMII_ID: 63 reg |= PORT_PCS_CTRL_RGMII_DELAY_RXCLK | 64 PORT_PCS_CTRL_RGMII_DELAY_TXCLK; 65 break; 66 case PHY_INTERFACE_MODE_RGMII: 67 break; 68 default: 69 return 0; 70 } 71 72 err = mv88e6xxx_port_write(chip, port, PORT_PCS_CTRL, reg); 73 if (err) 74 return err; 75 76 netdev_dbg(chip->ds->ports[port].netdev, "delay RXCLK %s, TXCLK %s\n", 77 reg & PORT_PCS_CTRL_RGMII_DELAY_RXCLK ? "yes" : "no", 78 reg & PORT_PCS_CTRL_RGMII_DELAY_TXCLK ? "yes" : "no"); 79 80 return 0; 81 } 82 83 int mv88e6352_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port, 84 phy_interface_t mode) 85 { 86 if (port < 5) 87 return -EOPNOTSUPP; 88 89 return mv88e6xxx_port_set_rgmii_delay(chip, port, mode); 90 } 91 92 int mv88e6390_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port, 93 phy_interface_t mode) 94 { 95 if (port != 0) 96 return -EOPNOTSUPP; 97 98 return mv88e6xxx_port_set_rgmii_delay(chip, port, mode); 99 } 100 101 int mv88e6xxx_port_set_link(struct mv88e6xxx_chip *chip, int port, int link) 102 { 103 u16 reg; 104 int err; 105 106 err = mv88e6xxx_port_read(chip, port, PORT_PCS_CTRL, ®); 107 if (err) 108 return err; 109 110 reg &= ~(PORT_PCS_CTRL_FORCE_LINK | PORT_PCS_CTRL_LINK_UP); 111 112 switch (link) { 113 case LINK_FORCED_DOWN: 114 reg |= PORT_PCS_CTRL_FORCE_LINK; 115 break; 116 case LINK_FORCED_UP: 117 reg |= PORT_PCS_CTRL_FORCE_LINK | PORT_PCS_CTRL_LINK_UP; 118 break; 119 case LINK_UNFORCED: 120 /* normal link detection */ 121 break; 122 default: 123 return -EINVAL; 124 } 125 126 err = mv88e6xxx_port_write(chip, port, PORT_PCS_CTRL, reg); 127 if (err) 128 return err; 129 130 netdev_dbg(chip->ds->ports[port].netdev, "%s link %s\n", 131 reg & PORT_PCS_CTRL_FORCE_LINK ? "Force" : "Unforce", 132 reg & PORT_PCS_CTRL_LINK_UP ? "up" : "down"); 133 134 return 0; 135 } 136 137 int mv88e6xxx_port_set_duplex(struct mv88e6xxx_chip *chip, int port, int dup) 138 { 139 u16 reg; 140 int err; 141 142 err = mv88e6xxx_port_read(chip, port, PORT_PCS_CTRL, ®); 143 if (err) 144 return err; 145 146 reg &= ~(PORT_PCS_CTRL_FORCE_DUPLEX | PORT_PCS_CTRL_DUPLEX_FULL); 147 148 switch (dup) { 149 case DUPLEX_HALF: 150 reg |= PORT_PCS_CTRL_FORCE_DUPLEX; 151 break; 152 case DUPLEX_FULL: 153 reg |= PORT_PCS_CTRL_FORCE_DUPLEX | PORT_PCS_CTRL_DUPLEX_FULL; 154 break; 155 case DUPLEX_UNFORCED: 156 /* normal duplex detection */ 157 break; 158 default: 159 return -EINVAL; 160 } 161 162 err = mv88e6xxx_port_write(chip, port, PORT_PCS_CTRL, reg); 163 if (err) 164 return err; 165 166 netdev_dbg(chip->ds->ports[port].netdev, "%s %s duplex\n", 167 reg & PORT_PCS_CTRL_FORCE_DUPLEX ? "Force" : "Unforce", 168 reg & PORT_PCS_CTRL_DUPLEX_FULL ? "full" : "half"); 169 170 return 0; 171 } 172 173 static int mv88e6xxx_port_set_speed(struct mv88e6xxx_chip *chip, int port, 174 int speed, bool alt_bit, bool force_bit) 175 { 176 u16 reg, ctrl; 177 int err; 178 179 switch (speed) { 180 case 10: 181 ctrl = PORT_PCS_CTRL_SPEED_10; 182 break; 183 case 100: 184 ctrl = PORT_PCS_CTRL_SPEED_100; 185 break; 186 case 200: 187 if (alt_bit) 188 ctrl = PORT_PCS_CTRL_SPEED_100 | PORT_PCS_CTRL_ALTSPEED; 189 else 190 ctrl = PORT_PCS_CTRL_SPEED_200; 191 break; 192 case 1000: 193 ctrl = PORT_PCS_CTRL_SPEED_1000; 194 break; 195 case 2500: 196 ctrl = PORT_PCS_CTRL_SPEED_1000 | PORT_PCS_CTRL_ALTSPEED; 197 break; 198 case 10000: 199 /* all bits set, fall through... */ 200 case SPEED_UNFORCED: 201 ctrl = PORT_PCS_CTRL_SPEED_UNFORCED; 202 break; 203 default: 204 return -EOPNOTSUPP; 205 } 206 207 err = mv88e6xxx_port_read(chip, port, PORT_PCS_CTRL, ®); 208 if (err) 209 return err; 210 211 reg &= ~PORT_PCS_CTRL_SPEED_MASK; 212 if (alt_bit) 213 reg &= ~PORT_PCS_CTRL_ALTSPEED; 214 if (force_bit) { 215 reg &= ~PORT_PCS_CTRL_FORCE_SPEED; 216 if (speed != SPEED_UNFORCED) 217 ctrl |= PORT_PCS_CTRL_FORCE_SPEED; 218 } 219 reg |= ctrl; 220 221 err = mv88e6xxx_port_write(chip, port, PORT_PCS_CTRL, reg); 222 if (err) 223 return err; 224 225 if (speed) 226 netdev_dbg(chip->ds->ports[port].netdev, 227 "Speed set to %d Mbps\n", speed); 228 else 229 netdev_dbg(chip->ds->ports[port].netdev, "Speed unforced\n"); 230 231 return 0; 232 } 233 234 /* Support 10, 100, 200 Mbps (e.g. 88E6065 family) */ 235 int mv88e6065_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed) 236 { 237 if (speed == SPEED_MAX) 238 speed = 200; 239 240 if (speed > 200) 241 return -EOPNOTSUPP; 242 243 /* Setting 200 Mbps on port 0 to 3 selects 100 Mbps */ 244 return mv88e6xxx_port_set_speed(chip, port, speed, false, false); 245 } 246 247 /* Support 10, 100, 1000 Mbps (e.g. 88E6185 family) */ 248 int mv88e6185_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed) 249 { 250 if (speed == SPEED_MAX) 251 speed = 1000; 252 253 if (speed == 200 || speed > 1000) 254 return -EOPNOTSUPP; 255 256 return mv88e6xxx_port_set_speed(chip, port, speed, false, false); 257 } 258 259 /* Support 10, 100, 200, 1000 Mbps (e.g. 88E6352 family) */ 260 int mv88e6352_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed) 261 { 262 if (speed == SPEED_MAX) 263 speed = 1000; 264 265 if (speed > 1000) 266 return -EOPNOTSUPP; 267 268 if (speed == 200 && port < 5) 269 return -EOPNOTSUPP; 270 271 return mv88e6xxx_port_set_speed(chip, port, speed, true, false); 272 } 273 274 /* Support 10, 100, 200, 1000, 2500 Mbps (e.g. 88E6390) */ 275 int mv88e6390_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed) 276 { 277 if (speed == SPEED_MAX) 278 speed = port < 9 ? 1000 : 2500; 279 280 if (speed > 2500) 281 return -EOPNOTSUPP; 282 283 if (speed == 200 && port != 0) 284 return -EOPNOTSUPP; 285 286 if (speed == 2500 && port < 9) 287 return -EOPNOTSUPP; 288 289 return mv88e6xxx_port_set_speed(chip, port, speed, true, true); 290 } 291 292 /* Support 10, 100, 200, 1000, 2500, 10000 Mbps (e.g. 88E6190X) */ 293 int mv88e6390x_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed) 294 { 295 if (speed == SPEED_MAX) 296 speed = port < 9 ? 1000 : 10000; 297 298 if (speed == 200 && port != 0) 299 return -EOPNOTSUPP; 300 301 if (speed >= 2500 && port < 9) 302 return -EOPNOTSUPP; 303 304 return mv88e6xxx_port_set_speed(chip, port, speed, true, true); 305 } 306 307 /* Offset 0x04: Port Control Register */ 308 309 static const char * const mv88e6xxx_port_state_names[] = { 310 [PORT_CONTROL_STATE_DISABLED] = "Disabled", 311 [PORT_CONTROL_STATE_BLOCKING] = "Blocking/Listening", 312 [PORT_CONTROL_STATE_LEARNING] = "Learning", 313 [PORT_CONTROL_STATE_FORWARDING] = "Forwarding", 314 }; 315 316 int mv88e6xxx_port_set_state(struct mv88e6xxx_chip *chip, int port, u8 state) 317 { 318 u16 reg; 319 int err; 320 321 err = mv88e6xxx_port_read(chip, port, PORT_CONTROL, ®); 322 if (err) 323 return err; 324 325 reg &= ~PORT_CONTROL_STATE_MASK; 326 reg |= state; 327 328 err = mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg); 329 if (err) 330 return err; 331 332 netdev_dbg(chip->ds->ports[port].netdev, "PortState set to %s\n", 333 mv88e6xxx_port_state_names[state]); 334 335 return 0; 336 } 337 338 /* Offset 0x05: Port Control 1 */ 339 340 /* Offset 0x06: Port Based VLAN Map */ 341 342 int mv88e6xxx_port_set_vlan_map(struct mv88e6xxx_chip *chip, int port, u16 map) 343 { 344 const u16 mask = GENMASK(mv88e6xxx_num_ports(chip) - 1, 0); 345 u16 reg; 346 int err; 347 348 err = mv88e6xxx_port_read(chip, port, PORT_BASE_VLAN, ®); 349 if (err) 350 return err; 351 352 reg &= ~mask; 353 reg |= map & mask; 354 355 err = mv88e6xxx_port_write(chip, port, PORT_BASE_VLAN, reg); 356 if (err) 357 return err; 358 359 netdev_dbg(chip->ds->ports[port].netdev, "VLANTable set to %.3x\n", 360 map); 361 362 return 0; 363 } 364 365 int mv88e6xxx_port_get_fid(struct mv88e6xxx_chip *chip, int port, u16 *fid) 366 { 367 const u16 upper_mask = (mv88e6xxx_num_databases(chip) - 1) >> 4; 368 u16 reg; 369 int err; 370 371 /* Port's default FID lower 4 bits are located in reg 0x06, offset 12 */ 372 err = mv88e6xxx_port_read(chip, port, PORT_BASE_VLAN, ®); 373 if (err) 374 return err; 375 376 *fid = (reg & 0xf000) >> 12; 377 378 /* Port's default FID upper bits are located in reg 0x05, offset 0 */ 379 if (upper_mask) { 380 err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_1, ®); 381 if (err) 382 return err; 383 384 *fid |= (reg & upper_mask) << 4; 385 } 386 387 return 0; 388 } 389 390 int mv88e6xxx_port_set_fid(struct mv88e6xxx_chip *chip, int port, u16 fid) 391 { 392 const u16 upper_mask = (mv88e6xxx_num_databases(chip) - 1) >> 4; 393 u16 reg; 394 int err; 395 396 if (fid >= mv88e6xxx_num_databases(chip)) 397 return -EINVAL; 398 399 /* Port's default FID lower 4 bits are located in reg 0x06, offset 12 */ 400 err = mv88e6xxx_port_read(chip, port, PORT_BASE_VLAN, ®); 401 if (err) 402 return err; 403 404 reg &= 0x0fff; 405 reg |= (fid & 0x000f) << 12; 406 407 err = mv88e6xxx_port_write(chip, port, PORT_BASE_VLAN, reg); 408 if (err) 409 return err; 410 411 /* Port's default FID upper bits are located in reg 0x05, offset 0 */ 412 if (upper_mask) { 413 err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_1, ®); 414 if (err) 415 return err; 416 417 reg &= ~upper_mask; 418 reg |= (fid >> 4) & upper_mask; 419 420 err = mv88e6xxx_port_write(chip, port, PORT_CONTROL_1, reg); 421 if (err) 422 return err; 423 } 424 425 netdev_dbg(chip->ds->ports[port].netdev, "FID set to %u\n", fid); 426 427 return 0; 428 } 429 430 /* Offset 0x07: Default Port VLAN ID & Priority */ 431 432 int mv88e6xxx_port_get_pvid(struct mv88e6xxx_chip *chip, int port, u16 *pvid) 433 { 434 u16 reg; 435 int err; 436 437 err = mv88e6xxx_port_read(chip, port, PORT_DEFAULT_VLAN, ®); 438 if (err) 439 return err; 440 441 *pvid = reg & PORT_DEFAULT_VLAN_MASK; 442 443 return 0; 444 } 445 446 int mv88e6xxx_port_set_pvid(struct mv88e6xxx_chip *chip, int port, u16 pvid) 447 { 448 u16 reg; 449 int err; 450 451 err = mv88e6xxx_port_read(chip, port, PORT_DEFAULT_VLAN, ®); 452 if (err) 453 return err; 454 455 reg &= ~PORT_DEFAULT_VLAN_MASK; 456 reg |= pvid & PORT_DEFAULT_VLAN_MASK; 457 458 err = mv88e6xxx_port_write(chip, port, PORT_DEFAULT_VLAN, reg); 459 if (err) 460 return err; 461 462 netdev_dbg(chip->ds->ports[port].netdev, "DefaultVID set to %u\n", 463 pvid); 464 465 return 0; 466 } 467 468 /* Offset 0x08: Port Control 2 Register */ 469 470 static const char * const mv88e6xxx_port_8021q_mode_names[] = { 471 [PORT_CONTROL_2_8021Q_DISABLED] = "Disabled", 472 [PORT_CONTROL_2_8021Q_FALLBACK] = "Fallback", 473 [PORT_CONTROL_2_8021Q_CHECK] = "Check", 474 [PORT_CONTROL_2_8021Q_SECURE] = "Secure", 475 }; 476 477 int mv88e6xxx_port_set_8021q_mode(struct mv88e6xxx_chip *chip, int port, 478 u16 mode) 479 { 480 u16 reg; 481 int err; 482 483 err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_2, ®); 484 if (err) 485 return err; 486 487 reg &= ~PORT_CONTROL_2_8021Q_MASK; 488 reg |= mode & PORT_CONTROL_2_8021Q_MASK; 489 490 err = mv88e6xxx_port_write(chip, port, PORT_CONTROL_2, reg); 491 if (err) 492 return err; 493 494 netdev_dbg(chip->ds->ports[port].netdev, "802.1QMode set to %s\n", 495 mv88e6xxx_port_8021q_mode_names[mode]); 496 497 return 0; 498 } 499 500 /* Offset 0x18: Port IEEE Priority Remapping Registers [0-3] 501 * Offset 0x19: Port IEEE Priority Remapping Registers [4-7] 502 */ 503 504 int mv88e6095_port_tag_remap(struct mv88e6xxx_chip *chip, int port) 505 { 506 int err; 507 508 /* Use a direct priority mapping for all IEEE tagged frames */ 509 err = mv88e6xxx_port_write(chip, port, PORT_TAG_REGMAP_0123, 0x3210); 510 if (err) 511 return err; 512 513 return mv88e6xxx_port_write(chip, port, PORT_TAG_REGMAP_4567, 0x7654); 514 } 515 516 static int mv88e6xxx_port_ieeepmt_write(struct mv88e6xxx_chip *chip, 517 int port, u16 table, 518 u8 pointer, u16 data) 519 { 520 u16 reg; 521 522 reg = PORT_IEEE_PRIO_MAP_TABLE_UPDATE | 523 table | 524 (pointer << PORT_IEEE_PRIO_MAP_TABLE_POINTER_SHIFT) | 525 data; 526 527 return mv88e6xxx_port_write(chip, port, PORT_IEEE_PRIO_MAP_TABLE, reg); 528 } 529 530 int mv88e6390_port_tag_remap(struct mv88e6xxx_chip *chip, int port) 531 { 532 int err, i; 533 534 for (i = 0; i <= 7; i++) { 535 err = mv88e6xxx_port_ieeepmt_write( 536 chip, port, PORT_IEEE_PRIO_MAP_TABLE_INGRESS_PCP, 537 i, (i | i << 4)); 538 if (err) 539 return err; 540 541 err = mv88e6xxx_port_ieeepmt_write( 542 chip, port, PORT_IEEE_PRIO_MAP_TABLE_EGRESS_GREEN_PCP, 543 i, i); 544 if (err) 545 return err; 546 547 err = mv88e6xxx_port_ieeepmt_write( 548 chip, port, PORT_IEEE_PRIO_MAP_TABLE_EGRESS_YELLOW_PCP, 549 i, i); 550 if (err) 551 return err; 552 553 err = mv88e6xxx_port_ieeepmt_write( 554 chip, port, PORT_IEEE_PRIO_MAP_TABLE_EGRESS_AVB_PCP, 555 i, i); 556 if (err) 557 return err; 558 } 559 560 return 0; 561 } 562