1 /* 2 * Marvell 88E6xxx Switch Global 2 Registers support (device address 0x1C) 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 "global2.h" 16 17 #define ADDR_GLOBAL2 0x1c 18 19 static int mv88e6xxx_g2_read(struct mv88e6xxx_chip *chip, int reg, u16 *val) 20 { 21 return mv88e6xxx_read(chip, ADDR_GLOBAL2, reg, val); 22 } 23 24 static int mv88e6xxx_g2_write(struct mv88e6xxx_chip *chip, int reg, u16 val) 25 { 26 return mv88e6xxx_write(chip, ADDR_GLOBAL2, reg, val); 27 } 28 29 static int mv88e6xxx_g2_update(struct mv88e6xxx_chip *chip, int reg, u16 update) 30 { 31 return mv88e6xxx_update(chip, ADDR_GLOBAL2, reg, update); 32 } 33 34 static int mv88e6xxx_g2_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask) 35 { 36 return mv88e6xxx_wait(chip, ADDR_GLOBAL2, reg, mask); 37 } 38 39 /* Offset 0x06: Device Mapping Table register */ 40 41 static int mv88e6xxx_g2_device_mapping_write(struct mv88e6xxx_chip *chip, 42 int target, int port) 43 { 44 u16 val = (target << 8) | (port & 0xf); 45 46 return mv88e6xxx_g2_update(chip, GLOBAL2_DEVICE_MAPPING, val); 47 } 48 49 static int mv88e6xxx_g2_set_device_mapping(struct mv88e6xxx_chip *chip) 50 { 51 int target, port; 52 int err; 53 54 /* Initialize the routing port to the 32 possible target devices */ 55 for (target = 0; target < 32; ++target) { 56 port = 0xf; 57 58 if (target < DSA_MAX_SWITCHES) { 59 port = chip->ds->rtable[target]; 60 if (port == DSA_RTABLE_NONE) 61 port = 0xf; 62 } 63 64 err = mv88e6xxx_g2_device_mapping_write(chip, target, port); 65 if (err) 66 break; 67 } 68 69 return err; 70 } 71 72 /* Offset 0x07: Trunk Mask Table register */ 73 74 static int mv88e6xxx_g2_trunk_mask_write(struct mv88e6xxx_chip *chip, int num, 75 bool hask, u16 mask) 76 { 77 const u16 port_mask = BIT(mv88e6xxx_num_ports(chip)) - 1; 78 u16 val = (num << 12) | (mask & port_mask); 79 80 if (hask) 81 val |= GLOBAL2_TRUNK_MASK_HASK; 82 83 return mv88e6xxx_g2_update(chip, GLOBAL2_TRUNK_MASK, val); 84 } 85 86 /* Offset 0x08: Trunk Mapping Table register */ 87 88 static int mv88e6xxx_g2_trunk_mapping_write(struct mv88e6xxx_chip *chip, int id, 89 u16 map) 90 { 91 const u16 port_mask = BIT(mv88e6xxx_num_ports(chip)) - 1; 92 u16 val = (id << 11) | (map & port_mask); 93 94 return mv88e6xxx_g2_update(chip, GLOBAL2_TRUNK_MAPPING, val); 95 } 96 97 static int mv88e6xxx_g2_clear_trunk(struct mv88e6xxx_chip *chip) 98 { 99 const u16 port_mask = BIT(mv88e6xxx_num_ports(chip)) - 1; 100 int i, err; 101 102 /* Clear all eight possible Trunk Mask vectors */ 103 for (i = 0; i < 8; ++i) { 104 err = mv88e6xxx_g2_trunk_mask_write(chip, i, false, port_mask); 105 if (err) 106 return err; 107 } 108 109 /* Clear all sixteen possible Trunk ID routing vectors */ 110 for (i = 0; i < 16; ++i) { 111 err = mv88e6xxx_g2_trunk_mapping_write(chip, i, 0); 112 if (err) 113 return err; 114 } 115 116 return 0; 117 } 118 119 /* Offset 0x09: Ingress Rate Command register 120 * Offset 0x0A: Ingress Rate Data register 121 */ 122 123 static int mv88e6xxx_g2_clear_irl(struct mv88e6xxx_chip *chip) 124 { 125 int port, err; 126 127 /* Init all Ingress Rate Limit resources of all ports */ 128 for (port = 0; port < mv88e6xxx_num_ports(chip); ++port) { 129 /* XXX newer chips (like 88E6390) have different 2-bit ops */ 130 err = mv88e6xxx_g2_write(chip, GLOBAL2_IRL_CMD, 131 GLOBAL2_IRL_CMD_OP_INIT_ALL | 132 (port << 8)); 133 if (err) 134 break; 135 136 /* Wait for the operation to complete */ 137 err = mv88e6xxx_g2_wait(chip, GLOBAL2_IRL_CMD, 138 GLOBAL2_IRL_CMD_BUSY); 139 if (err) 140 break; 141 } 142 143 return err; 144 } 145 146 /* Offset 0x0D: Switch MAC/WoL/WoF register */ 147 148 static int mv88e6xxx_g2_switch_mac_write(struct mv88e6xxx_chip *chip, 149 unsigned int pointer, u8 data) 150 { 151 u16 val = (pointer << 8) | data; 152 153 return mv88e6xxx_g2_update(chip, GLOBAL2_SWITCH_MAC, val); 154 } 155 156 int mv88e6xxx_g2_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr) 157 { 158 int i, err; 159 160 for (i = 0; i < 6; i++) { 161 err = mv88e6xxx_g2_switch_mac_write(chip, i, addr[i]); 162 if (err) 163 break; 164 } 165 166 return err; 167 } 168 169 /* Offset 0x0F: Priority Override Table */ 170 171 static int mv88e6xxx_g2_pot_write(struct mv88e6xxx_chip *chip, int pointer, 172 u8 data) 173 { 174 u16 val = (pointer << 8) | (data & 0x7); 175 176 return mv88e6xxx_g2_update(chip, GLOBAL2_PRIO_OVERRIDE, val); 177 } 178 179 static int mv88e6xxx_g2_clear_pot(struct mv88e6xxx_chip *chip) 180 { 181 int i, err; 182 183 /* Clear all sixteen possible Priority Override entries */ 184 for (i = 0; i < 16; i++) { 185 err = mv88e6xxx_g2_pot_write(chip, i, 0); 186 if (err) 187 break; 188 } 189 190 return err; 191 } 192 193 /* Offset 0x14: EEPROM Command 194 * Offset 0x15: EEPROM Data 195 */ 196 197 static int mv88e6xxx_g2_eeprom_wait(struct mv88e6xxx_chip *chip) 198 { 199 return mv88e6xxx_g2_wait(chip, GLOBAL2_EEPROM_CMD, 200 GLOBAL2_EEPROM_CMD_BUSY | 201 GLOBAL2_EEPROM_CMD_RUNNING); 202 } 203 204 static int mv88e6xxx_g2_eeprom_cmd(struct mv88e6xxx_chip *chip, u16 cmd) 205 { 206 int err; 207 208 err = mv88e6xxx_g2_write(chip, GLOBAL2_EEPROM_CMD, cmd); 209 if (err) 210 return err; 211 212 return mv88e6xxx_g2_eeprom_wait(chip); 213 } 214 215 static int mv88e6xxx_g2_eeprom_read16(struct mv88e6xxx_chip *chip, 216 u8 addr, u16 *data) 217 { 218 u16 cmd = GLOBAL2_EEPROM_CMD_OP_READ | addr; 219 int err; 220 221 err = mv88e6xxx_g2_eeprom_wait(chip); 222 if (err) 223 return err; 224 225 err = mv88e6xxx_g2_eeprom_cmd(chip, cmd); 226 if (err) 227 return err; 228 229 return mv88e6xxx_g2_read(chip, GLOBAL2_EEPROM_DATA, data); 230 } 231 232 static int mv88e6xxx_g2_eeprom_write16(struct mv88e6xxx_chip *chip, 233 u8 addr, u16 data) 234 { 235 u16 cmd = GLOBAL2_EEPROM_CMD_OP_WRITE | addr; 236 int err; 237 238 err = mv88e6xxx_g2_eeprom_wait(chip); 239 if (err) 240 return err; 241 242 err = mv88e6xxx_g2_write(chip, GLOBAL2_EEPROM_DATA, data); 243 if (err) 244 return err; 245 246 return mv88e6xxx_g2_eeprom_cmd(chip, cmd); 247 } 248 249 int mv88e6xxx_g2_get_eeprom16(struct mv88e6xxx_chip *chip, 250 struct ethtool_eeprom *eeprom, u8 *data) 251 { 252 unsigned int offset = eeprom->offset; 253 unsigned int len = eeprom->len; 254 u16 val; 255 int err; 256 257 eeprom->len = 0; 258 259 if (offset & 1) { 260 err = mv88e6xxx_g2_eeprom_read16(chip, offset >> 1, &val); 261 if (err) 262 return err; 263 264 *data++ = (val >> 8) & 0xff; 265 266 offset++; 267 len--; 268 eeprom->len++; 269 } 270 271 while (len >= 2) { 272 err = mv88e6xxx_g2_eeprom_read16(chip, offset >> 1, &val); 273 if (err) 274 return err; 275 276 *data++ = val & 0xff; 277 *data++ = (val >> 8) & 0xff; 278 279 offset += 2; 280 len -= 2; 281 eeprom->len += 2; 282 } 283 284 if (len) { 285 err = mv88e6xxx_g2_eeprom_read16(chip, offset >> 1, &val); 286 if (err) 287 return err; 288 289 *data++ = val & 0xff; 290 291 offset++; 292 len--; 293 eeprom->len++; 294 } 295 296 return 0; 297 } 298 299 int mv88e6xxx_g2_set_eeprom16(struct mv88e6xxx_chip *chip, 300 struct ethtool_eeprom *eeprom, u8 *data) 301 { 302 unsigned int offset = eeprom->offset; 303 unsigned int len = eeprom->len; 304 u16 val; 305 int err; 306 307 /* Ensure the RO WriteEn bit is set */ 308 err = mv88e6xxx_g2_read(chip, GLOBAL2_EEPROM_CMD, &val); 309 if (err) 310 return err; 311 312 if (!(val & GLOBAL2_EEPROM_CMD_WRITE_EN)) 313 return -EROFS; 314 315 eeprom->len = 0; 316 317 if (offset & 1) { 318 err = mv88e6xxx_g2_eeprom_read16(chip, offset >> 1, &val); 319 if (err) 320 return err; 321 322 val = (*data++ << 8) | (val & 0xff); 323 324 err = mv88e6xxx_g2_eeprom_write16(chip, offset >> 1, val); 325 if (err) 326 return err; 327 328 offset++; 329 len--; 330 eeprom->len++; 331 } 332 333 while (len >= 2) { 334 val = *data++; 335 val |= *data++ << 8; 336 337 err = mv88e6xxx_g2_eeprom_write16(chip, offset >> 1, val); 338 if (err) 339 return err; 340 341 offset += 2; 342 len -= 2; 343 eeprom->len += 2; 344 } 345 346 if (len) { 347 err = mv88e6xxx_g2_eeprom_read16(chip, offset >> 1, &val); 348 if (err) 349 return err; 350 351 val = (val & 0xff00) | *data++; 352 353 err = mv88e6xxx_g2_eeprom_write16(chip, offset >> 1, val); 354 if (err) 355 return err; 356 357 offset++; 358 len--; 359 eeprom->len++; 360 } 361 362 return 0; 363 } 364 365 /* Offset 0x18: SMI PHY Command Register 366 * Offset 0x19: SMI PHY Data Register 367 */ 368 369 static int mv88e6xxx_g2_smi_phy_wait(struct mv88e6xxx_chip *chip) 370 { 371 return mv88e6xxx_g2_wait(chip, GLOBAL2_SMI_PHY_CMD, 372 GLOBAL2_SMI_PHY_CMD_BUSY); 373 } 374 375 static int mv88e6xxx_g2_smi_phy_cmd(struct mv88e6xxx_chip *chip, u16 cmd) 376 { 377 int err; 378 379 err = mv88e6xxx_g2_write(chip, GLOBAL2_SMI_PHY_CMD, cmd); 380 if (err) 381 return err; 382 383 return mv88e6xxx_g2_smi_phy_wait(chip); 384 } 385 386 int mv88e6xxx_g2_smi_phy_read(struct mv88e6xxx_chip *chip, int addr, int reg, 387 u16 *val) 388 { 389 u16 cmd = GLOBAL2_SMI_PHY_CMD_OP_22_READ_DATA | (addr << 5) | reg; 390 int err; 391 392 err = mv88e6xxx_g2_smi_phy_wait(chip); 393 if (err) 394 return err; 395 396 err = mv88e6xxx_g2_smi_phy_cmd(chip, cmd); 397 if (err) 398 return err; 399 400 return mv88e6xxx_g2_read(chip, GLOBAL2_SMI_PHY_DATA, val); 401 } 402 403 int mv88e6xxx_g2_smi_phy_write(struct mv88e6xxx_chip *chip, int addr, int reg, 404 u16 val) 405 { 406 u16 cmd = GLOBAL2_SMI_PHY_CMD_OP_22_WRITE_DATA | (addr << 5) | reg; 407 int err; 408 409 err = mv88e6xxx_g2_smi_phy_wait(chip); 410 if (err) 411 return err; 412 413 err = mv88e6xxx_g2_write(chip, GLOBAL2_SMI_PHY_DATA, val); 414 if (err) 415 return err; 416 417 return mv88e6xxx_g2_smi_phy_cmd(chip, cmd); 418 } 419 420 int mv88e6xxx_g2_setup(struct mv88e6xxx_chip *chip) 421 { 422 u16 reg; 423 int err; 424 425 if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_2X)) { 426 /* Consider the frames with reserved multicast destination 427 * addresses matching 01:80:c2:00:00:2x as MGMT. 428 */ 429 err = mv88e6xxx_g2_write(chip, GLOBAL2_MGMT_EN_2X, 0xffff); 430 if (err) 431 return err; 432 } 433 434 if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_0X)) { 435 /* Consider the frames with reserved multicast destination 436 * addresses matching 01:80:c2:00:00:0x as MGMT. 437 */ 438 err = mv88e6xxx_g2_write(chip, GLOBAL2_MGMT_EN_0X, 0xffff); 439 if (err) 440 return err; 441 } 442 443 /* Ignore removed tag data on doubly tagged packets, disable 444 * flow control messages, force flow control priority to the 445 * highest, and send all special multicast frames to the CPU 446 * port at the highest priority. 447 */ 448 reg = GLOBAL2_SWITCH_MGMT_FORCE_FLOW_CTRL_PRI | (0x7 << 4); 449 if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_0X) || 450 mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_2X)) 451 reg |= GLOBAL2_SWITCH_MGMT_RSVD2CPU | 0x7; 452 err = mv88e6xxx_g2_write(chip, GLOBAL2_SWITCH_MGMT, reg); 453 if (err) 454 return err; 455 456 /* Program the DSA routing table. */ 457 err = mv88e6xxx_g2_set_device_mapping(chip); 458 if (err) 459 return err; 460 461 /* Clear all trunk masks and mapping. */ 462 err = mv88e6xxx_g2_clear_trunk(chip); 463 if (err) 464 return err; 465 466 if (mv88e6xxx_has(chip, MV88E6XXX_FLAGS_IRL)) { 467 /* Disable ingress rate limiting by resetting all per port 468 * ingress rate limit resources to their initial state. 469 */ 470 err = mv88e6xxx_g2_clear_irl(chip); 471 if (err) 472 return err; 473 } 474 475 if (mv88e6xxx_has(chip, MV88E6XXX_FLAGS_PVT)) { 476 /* Initialize Cross-chip Port VLAN Table to reset defaults */ 477 err = mv88e6xxx_g2_write(chip, GLOBAL2_PVT_ADDR, 478 GLOBAL2_PVT_ADDR_OP_INIT_ONES); 479 if (err) 480 return err; 481 } 482 483 if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_POT)) { 484 /* Clear the priority override table. */ 485 err = mv88e6xxx_g2_clear_pot(chip); 486 if (err) 487 return err; 488 } 489 490 return 0; 491 } 492