1/* 2 * net/dsa/mv88e6352.c - Marvell 88e6352 switch chip support 3 * 4 * Copyright (c) 2014 Guenter Roeck 5 * 6 * Derived from mv88e6123_61_65.c 7 * Copyright (c) 2008-2009 Marvell Semiconductor 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/delay.h> 16#include <linux/jiffies.h> 17#include <linux/list.h> 18#include <linux/module.h> 19#include <linux/netdevice.h> 20#include <linux/platform_device.h> 21#include <linux/phy.h> 22#include <net/dsa.h> 23#include "mv88e6xxx.h" 24 25static char *mv88e6352_probe(struct device *host_dev, int sw_addr) 26{ 27 struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev); 28 int ret; 29 30 if (bus == NULL) 31 return NULL; 32 33 ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), PORT_SWITCH_ID); 34 if (ret >= 0) { 35 if ((ret & 0xfff0) == PORT_SWITCH_ID_6176) 36 return "Marvell 88E6176"; 37 if (ret == PORT_SWITCH_ID_6352_A0) 38 return "Marvell 88E6352 (A0)"; 39 if (ret == PORT_SWITCH_ID_6352_A1) 40 return "Marvell 88E6352 (A1)"; 41 if ((ret & 0xfff0) == PORT_SWITCH_ID_6352) 42 return "Marvell 88E6352"; 43 } 44 45 return NULL; 46} 47 48static int mv88e6352_setup_global(struct dsa_switch *ds) 49{ 50 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); 51 int ret; 52 int i; 53 54 /* Discard packets with excessive collisions, 55 * mask all interrupt sources, enable PPU (bit 14, undocumented). 56 */ 57 REG_WRITE(REG_GLOBAL, 0x04, 0x6000); 58 59 /* Set the default address aging time to 5 minutes, and 60 * enable address learn messages to be sent to all message 61 * ports. 62 */ 63 REG_WRITE(REG_GLOBAL, 0x0a, 0x0148); 64 65 /* Configure the priority mapping registers. */ 66 ret = mv88e6xxx_config_prio(ds); 67 if (ret < 0) 68 return ret; 69 70 /* Configure the upstream port, and configure the upstream 71 * port as the port to which ingress and egress monitor frames 72 * are to be sent. 73 */ 74 REG_WRITE(REG_GLOBAL, 0x1a, (dsa_upstream_port(ds) * 0x1110)); 75 76 /* Disable remote management for now, and set the switch's 77 * DSA device number. 78 */ 79 REG_WRITE(REG_GLOBAL, 0x1c, ds->index & 0x1f); 80 81 /* Send all frames with destination addresses matching 82 * 01:80:c2:00:00:2x to the CPU port. 83 */ 84 REG_WRITE(REG_GLOBAL2, 0x02, 0xffff); 85 86 /* Send all frames with destination addresses matching 87 * 01:80:c2:00:00:0x to the CPU port. 88 */ 89 REG_WRITE(REG_GLOBAL2, 0x03, 0xffff); 90 91 /* Disable the loopback filter, disable flow control 92 * messages, disable flood broadcast override, disable 93 * removing of provider tags, disable ATU age violation 94 * interrupts, disable tag flow control, force flow 95 * control priority to the highest, and send all special 96 * multicast frames to the CPU at the highest priority. 97 */ 98 REG_WRITE(REG_GLOBAL2, 0x05, 0x00ff); 99 100 /* Program the DSA routing table. */ 101 for (i = 0; i < 32; i++) { 102 int nexthop = 0x1f; 103 104 if (i != ds->index && i < ds->dst->pd->nr_chips) 105 nexthop = ds->pd->rtable[i] & 0x1f; 106 107 REG_WRITE(REG_GLOBAL2, 0x06, 0x8000 | (i << 8) | nexthop); 108 } 109 110 /* Clear all trunk masks. */ 111 for (i = 0; i < 8; i++) 112 REG_WRITE(REG_GLOBAL2, 0x07, 0x8000 | (i << 12) | 0x7f); 113 114 /* Clear all trunk mappings. */ 115 for (i = 0; i < 16; i++) 116 REG_WRITE(REG_GLOBAL2, 0x08, 0x8000 | (i << 11)); 117 118 /* Disable ingress rate limiting by resetting all ingress 119 * rate limit registers to their initial state. 120 */ 121 for (i = 0; i < ps->num_ports; i++) 122 REG_WRITE(REG_GLOBAL2, 0x09, 0x9000 | (i << 8)); 123 124 /* Initialise cross-chip port VLAN table to reset defaults. */ 125 REG_WRITE(REG_GLOBAL2, 0x0b, 0x9000); 126 127 /* Clear the priority override table. */ 128 for (i = 0; i < 16; i++) 129 REG_WRITE(REG_GLOBAL2, 0x0f, 0x8000 | (i << 8)); 130 131 /* @@@ initialise AVB (22/23) watchdog (27) sdet (29) registers */ 132 133 return 0; 134} 135 136static int mv88e6352_setup_port(struct dsa_switch *ds, int p) 137{ 138 int addr = REG_PORT(p); 139 u16 val; 140 141 /* MAC Forcing register: don't force link, speed, duplex 142 * or flow control state to any particular values on physical 143 * ports, but force the CPU port and all DSA ports to 1000 Mb/s 144 * full duplex. 145 */ 146 if (dsa_is_cpu_port(ds, p) || ds->dsa_port_mask & (1 << p)) 147 REG_WRITE(addr, 0x01, 0x003e); 148 else 149 REG_WRITE(addr, 0x01, 0x0003); 150 151 /* Do not limit the period of time that this port can be 152 * paused for by the remote end or the period of time that 153 * this port can pause the remote end. 154 */ 155 REG_WRITE(addr, 0x02, 0x0000); 156 157 /* Port Control: disable Drop-on-Unlock, disable Drop-on-Lock, 158 * disable Header mode, enable IGMP/MLD snooping, disable VLAN 159 * tunneling, determine priority by looking at 802.1p and IP 160 * priority fields (IP prio has precedence), and set STP state 161 * to Forwarding. 162 * 163 * If this is the CPU link, use DSA or EDSA tagging depending 164 * on which tagging mode was configured. 165 * 166 * If this is a link to another switch, use DSA tagging mode. 167 * 168 * If this is the upstream port for this switch, enable 169 * forwarding of unknown unicasts and multicasts. 170 */ 171 val = 0x0433; 172 if (dsa_is_cpu_port(ds, p)) { 173 if (ds->dst->tag_protocol == DSA_TAG_PROTO_EDSA) 174 val |= 0x3300; 175 else 176 val |= 0x0100; 177 } 178 if (ds->dsa_port_mask & (1 << p)) 179 val |= 0x0100; 180 if (p == dsa_upstream_port(ds)) 181 val |= 0x000c; 182 REG_WRITE(addr, 0x04, val); 183 184 /* Port Control 2: don't force a good FCS, set the maximum 185 * frame size to 10240 bytes, don't let the switch add or 186 * strip 802.1q tags, don't discard tagged or untagged frames 187 * on this port, do a destination address lookup on all 188 * received packets as usual, disable ARP mirroring and don't 189 * send a copy of all transmitted/received frames on this port 190 * to the CPU. 191 */ 192 REG_WRITE(addr, 0x08, 0x2080); 193 194 /* Egress rate control: disable egress rate control. */ 195 REG_WRITE(addr, 0x09, 0x0001); 196 197 /* Egress rate control 2: disable egress rate control. */ 198 REG_WRITE(addr, 0x0a, 0x0000); 199 200 /* Port Association Vector: when learning source addresses 201 * of packets, add the address to the address database using 202 * a port bitmap that has only the bit for this port set and 203 * the other bits clear. 204 */ 205 REG_WRITE(addr, 0x0b, 1 << p); 206 207 /* Port ATU control: disable limiting the number of address 208 * database entries that this port is allowed to use. 209 */ 210 REG_WRITE(addr, 0x0c, 0x0000); 211 212 /* Priority Override: disable DA, SA and VTU priority override. */ 213 REG_WRITE(addr, 0x0d, 0x0000); 214 215 /* Port Ethertype: use the Ethertype DSA Ethertype value. */ 216 REG_WRITE(addr, 0x0f, ETH_P_EDSA); 217 218 /* Tag Remap: use an identity 802.1p prio -> switch prio 219 * mapping. 220 */ 221 REG_WRITE(addr, 0x18, 0x3210); 222 223 /* Tag Remap 2: use an identity 802.1p prio -> switch prio 224 * mapping. 225 */ 226 REG_WRITE(addr, 0x19, 0x7654); 227 228 return mv88e6xxx_setup_port_common(ds, p); 229} 230 231#ifdef CONFIG_NET_DSA_HWMON 232 233static int mv88e6352_get_temp(struct dsa_switch *ds, int *temp) 234{ 235 int ret; 236 237 *temp = 0; 238 239 ret = mv88e6xxx_phy_page_read(ds, 0, 6, 27); 240 if (ret < 0) 241 return ret; 242 243 *temp = (ret & 0xff) - 25; 244 245 return 0; 246} 247 248static int mv88e6352_get_temp_limit(struct dsa_switch *ds, int *temp) 249{ 250 int ret; 251 252 *temp = 0; 253 254 ret = mv88e6xxx_phy_page_read(ds, 0, 6, 26); 255 if (ret < 0) 256 return ret; 257 258 *temp = (((ret >> 8) & 0x1f) * 5) - 25; 259 260 return 0; 261} 262 263static int mv88e6352_set_temp_limit(struct dsa_switch *ds, int temp) 264{ 265 int ret; 266 267 ret = mv88e6xxx_phy_page_read(ds, 0, 6, 26); 268 if (ret < 0) 269 return ret; 270 temp = clamp_val(DIV_ROUND_CLOSEST(temp, 5) + 5, 0, 0x1f); 271 return mv88e6xxx_phy_page_write(ds, 0, 6, 26, 272 (ret & 0xe0ff) | (temp << 8)); 273} 274 275static int mv88e6352_get_temp_alarm(struct dsa_switch *ds, bool *alarm) 276{ 277 int ret; 278 279 *alarm = false; 280 281 ret = mv88e6xxx_phy_page_read(ds, 0, 6, 26); 282 if (ret < 0) 283 return ret; 284 285 *alarm = !!(ret & 0x40); 286 287 return 0; 288} 289#endif /* CONFIG_NET_DSA_HWMON */ 290 291static int mv88e6352_setup(struct dsa_switch *ds) 292{ 293 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); 294 int ret; 295 int i; 296 297 ret = mv88e6xxx_setup_common(ds); 298 if (ret < 0) 299 return ret; 300 301 ps->num_ports = 7; 302 303 mutex_init(&ps->eeprom_mutex); 304 305 ret = mv88e6xxx_switch_reset(ds, true); 306 if (ret < 0) 307 return ret; 308 309 /* @@@ initialise vtu and atu */ 310 311 ret = mv88e6352_setup_global(ds); 312 if (ret < 0) 313 return ret; 314 315 for (i = 0; i < ps->num_ports; i++) { 316 ret = mv88e6352_setup_port(ds, i); 317 if (ret < 0) 318 return ret; 319 } 320 321 return 0; 322} 323 324static int mv88e6352_read_eeprom_word(struct dsa_switch *ds, int addr) 325{ 326 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); 327 int ret; 328 329 mutex_lock(&ps->eeprom_mutex); 330 331 ret = mv88e6xxx_reg_write(ds, REG_GLOBAL2, 0x14, 332 0xc000 | (addr & 0xff)); 333 if (ret < 0) 334 goto error; 335 336 ret = mv88e6xxx_eeprom_busy_wait(ds); 337 if (ret < 0) 338 goto error; 339 340 ret = mv88e6xxx_reg_read(ds, REG_GLOBAL2, 0x15); 341error: 342 mutex_unlock(&ps->eeprom_mutex); 343 return ret; 344} 345 346static int mv88e6352_get_eeprom(struct dsa_switch *ds, 347 struct ethtool_eeprom *eeprom, u8 *data) 348{ 349 int offset; 350 int len; 351 int ret; 352 353 offset = eeprom->offset; 354 len = eeprom->len; 355 eeprom->len = 0; 356 357 eeprom->magic = 0xc3ec4951; 358 359 ret = mv88e6xxx_eeprom_load_wait(ds); 360 if (ret < 0) 361 return ret; 362 363 if (offset & 1) { 364 int word; 365 366 word = mv88e6352_read_eeprom_word(ds, offset >> 1); 367 if (word < 0) 368 return word; 369 370 *data++ = (word >> 8) & 0xff; 371 372 offset++; 373 len--; 374 eeprom->len++; 375 } 376 377 while (len >= 2) { 378 int word; 379 380 word = mv88e6352_read_eeprom_word(ds, offset >> 1); 381 if (word < 0) 382 return word; 383 384 *data++ = word & 0xff; 385 *data++ = (word >> 8) & 0xff; 386 387 offset += 2; 388 len -= 2; 389 eeprom->len += 2; 390 } 391 392 if (len) { 393 int word; 394 395 word = mv88e6352_read_eeprom_word(ds, offset >> 1); 396 if (word < 0) 397 return word; 398 399 *data++ = word & 0xff; 400 401 offset++; 402 len--; 403 eeprom->len++; 404 } 405 406 return 0; 407} 408 409static int mv88e6352_eeprom_is_readonly(struct dsa_switch *ds) 410{ 411 int ret; 412 413 ret = mv88e6xxx_reg_read(ds, REG_GLOBAL2, 0x14); 414 if (ret < 0) 415 return ret; 416 417 if (!(ret & 0x0400)) 418 return -EROFS; 419 420 return 0; 421} 422 423static int mv88e6352_write_eeprom_word(struct dsa_switch *ds, int addr, 424 u16 data) 425{ 426 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); 427 int ret; 428 429 mutex_lock(&ps->eeprom_mutex); 430 431 ret = mv88e6xxx_reg_write(ds, REG_GLOBAL2, 0x15, data); 432 if (ret < 0) 433 goto error; 434 435 ret = mv88e6xxx_reg_write(ds, REG_GLOBAL2, 0x14, 436 0xb000 | (addr & 0xff)); 437 if (ret < 0) 438 goto error; 439 440 ret = mv88e6xxx_eeprom_busy_wait(ds); 441error: 442 mutex_unlock(&ps->eeprom_mutex); 443 return ret; 444} 445 446static int mv88e6352_set_eeprom(struct dsa_switch *ds, 447 struct ethtool_eeprom *eeprom, u8 *data) 448{ 449 int offset; 450 int ret; 451 int len; 452 453 if (eeprom->magic != 0xc3ec4951) 454 return -EINVAL; 455 456 ret = mv88e6352_eeprom_is_readonly(ds); 457 if (ret) 458 return ret; 459 460 offset = eeprom->offset; 461 len = eeprom->len; 462 eeprom->len = 0; 463 464 ret = mv88e6xxx_eeprom_load_wait(ds); 465 if (ret < 0) 466 return ret; 467 468 if (offset & 1) { 469 int word; 470 471 word = mv88e6352_read_eeprom_word(ds, offset >> 1); 472 if (word < 0) 473 return word; 474 475 word = (*data++ << 8) | (word & 0xff); 476 477 ret = mv88e6352_write_eeprom_word(ds, offset >> 1, word); 478 if (ret < 0) 479 return ret; 480 481 offset++; 482 len--; 483 eeprom->len++; 484 } 485 486 while (len >= 2) { 487 int word; 488 489 word = *data++; 490 word |= *data++ << 8; 491 492 ret = mv88e6352_write_eeprom_word(ds, offset >> 1, word); 493 if (ret < 0) 494 return ret; 495 496 offset += 2; 497 len -= 2; 498 eeprom->len += 2; 499 } 500 501 if (len) { 502 int word; 503 504 word = mv88e6352_read_eeprom_word(ds, offset >> 1); 505 if (word < 0) 506 return word; 507 508 word = (word & 0xff00) | *data++; 509 510 ret = mv88e6352_write_eeprom_word(ds, offset >> 1, word); 511 if (ret < 0) 512 return ret; 513 514 offset++; 515 len--; 516 eeprom->len++; 517 } 518 519 return 0; 520} 521 522struct dsa_switch_driver mv88e6352_switch_driver = { 523 .tag_protocol = DSA_TAG_PROTO_EDSA, 524 .priv_size = sizeof(struct mv88e6xxx_priv_state), 525 .probe = mv88e6352_probe, 526 .setup = mv88e6352_setup, 527 .set_addr = mv88e6xxx_set_addr_indirect, 528 .phy_read = mv88e6xxx_phy_read_indirect, 529 .phy_write = mv88e6xxx_phy_write_indirect, 530 .poll_link = mv88e6xxx_poll_link, 531 .get_strings = mv88e6xxx_get_strings, 532 .get_ethtool_stats = mv88e6xxx_get_ethtool_stats, 533 .get_sset_count = mv88e6xxx_get_sset_count, 534 .set_eee = mv88e6xxx_set_eee, 535 .get_eee = mv88e6xxx_get_eee, 536#ifdef CONFIG_NET_DSA_HWMON 537 .get_temp = mv88e6352_get_temp, 538 .get_temp_limit = mv88e6352_get_temp_limit, 539 .set_temp_limit = mv88e6352_set_temp_limit, 540 .get_temp_alarm = mv88e6352_get_temp_alarm, 541#endif 542 .get_eeprom = mv88e6352_get_eeprom, 543 .set_eeprom = mv88e6352_set_eeprom, 544 .get_regs_len = mv88e6xxx_get_regs_len, 545 .get_regs = mv88e6xxx_get_regs, 546 .port_join_bridge = mv88e6xxx_join_bridge, 547 .port_leave_bridge = mv88e6xxx_leave_bridge, 548 .port_stp_update = mv88e6xxx_port_stp_update, 549 .fdb_add = mv88e6xxx_port_fdb_add, 550 .fdb_del = mv88e6xxx_port_fdb_del, 551 .fdb_getnext = mv88e6xxx_port_fdb_getnext, 552}; 553 554MODULE_ALIAS("platform:mv88e6352"); 555