1/* 2 * net/dsa/mv88e6123_61_65.c - Marvell 88e6123/6161/6165 switch chip support 3 * Copyright (c) 2008-2009 Marvell Semiconductor 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 */ 10 11#include <linux/delay.h> 12#include <linux/jiffies.h> 13#include <linux/list.h> 14#include <linux/module.h> 15#include <linux/netdevice.h> 16#include <linux/phy.h> 17#include <net/dsa.h> 18#include "mv88e6xxx.h" 19 20static char *mv88e6123_61_65_probe(struct device *host_dev, int sw_addr) 21{ 22 struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev); 23 int ret; 24 25 if (bus == NULL) 26 return NULL; 27 28 ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), PORT_SWITCH_ID); 29 if (ret >= 0) { 30 if (ret == PORT_SWITCH_ID_6123_A1) 31 return "Marvell 88E6123 (A1)"; 32 if (ret == PORT_SWITCH_ID_6123_A2) 33 return "Marvell 88E6123 (A2)"; 34 if ((ret & 0xfff0) == PORT_SWITCH_ID_6123) 35 return "Marvell 88E6123"; 36 37 if (ret == PORT_SWITCH_ID_6161_A1) 38 return "Marvell 88E6161 (A1)"; 39 if (ret == PORT_SWITCH_ID_6161_A2) 40 return "Marvell 88E6161 (A2)"; 41 if ((ret & 0xfff0) == PORT_SWITCH_ID_6161) 42 return "Marvell 88E6161"; 43 44 if (ret == PORT_SWITCH_ID_6165_A1) 45 return "Marvell 88E6165 (A1)"; 46 if (ret == PORT_SWITCH_ID_6165_A2) 47 return "Marvell 88e6165 (A2)"; 48 if ((ret & 0xfff0) == PORT_SWITCH_ID_6165) 49 return "Marvell 88E6165"; 50 } 51 52 return NULL; 53} 54 55static int mv88e6123_61_65_setup_global(struct dsa_switch *ds) 56{ 57 int ret; 58 int i; 59 60 /* Disable the PHY polling unit (since there won't be any 61 * external PHYs to poll), don't discard packets with 62 * excessive collisions, and mask all interrupt sources. 63 */ 64 REG_WRITE(REG_GLOBAL, 0x04, 0x0000); 65 66 /* Set the default address aging time to 5 minutes, and 67 * enable address learn messages to be sent to all message 68 * ports. 69 */ 70 REG_WRITE(REG_GLOBAL, 0x0a, 0x0148); 71 72 /* Configure the priority mapping registers. */ 73 ret = mv88e6xxx_config_prio(ds); 74 if (ret < 0) 75 return ret; 76 77 /* Configure the upstream port, and configure the upstream 78 * port as the port to which ingress and egress monitor frames 79 * are to be sent. 80 */ 81 REG_WRITE(REG_GLOBAL, 0x1a, (dsa_upstream_port(ds) * 0x1110)); 82 83 /* Disable remote management for now, and set the switch's 84 * DSA device number. 85 */ 86 REG_WRITE(REG_GLOBAL, 0x1c, ds->index & 0x1f); 87 88 /* Send all frames with destination addresses matching 89 * 01:80:c2:00:00:2x to the CPU port. 90 */ 91 REG_WRITE(REG_GLOBAL2, 0x02, 0xffff); 92 93 /* Send all frames with destination addresses matching 94 * 01:80:c2:00:00:0x to the CPU port. 95 */ 96 REG_WRITE(REG_GLOBAL2, 0x03, 0xffff); 97 98 /* Disable the loopback filter, disable flow control 99 * messages, disable flood broadcast override, disable 100 * removing of provider tags, disable ATU age violation 101 * interrupts, disable tag flow control, force flow 102 * control priority to the highest, and send all special 103 * multicast frames to the CPU at the highest priority. 104 */ 105 REG_WRITE(REG_GLOBAL2, 0x05, 0x00ff); 106 107 /* Program the DSA routing table. */ 108 for (i = 0; i < 32; i++) { 109 int nexthop; 110 111 nexthop = 0x1f; 112 if (i != ds->index && i < ds->dst->pd->nr_chips) 113 nexthop = ds->pd->rtable[i] & 0x1f; 114 115 REG_WRITE(REG_GLOBAL2, 0x06, 0x8000 | (i << 8) | nexthop); 116 } 117 118 /* Clear all trunk masks. */ 119 for (i = 0; i < 8; i++) 120 REG_WRITE(REG_GLOBAL2, 0x07, 0x8000 | (i << 12) | 0xff); 121 122 /* Clear all trunk mappings. */ 123 for (i = 0; i < 16; i++) 124 REG_WRITE(REG_GLOBAL2, 0x08, 0x8000 | (i << 11)); 125 126 /* Disable ingress rate limiting by resetting all ingress 127 * rate limit registers to their initial state. 128 */ 129 for (i = 0; i < 6; i++) 130 REG_WRITE(REG_GLOBAL2, 0x09, 0x9000 | (i << 8)); 131 132 /* Initialise cross-chip port VLAN table to reset defaults. */ 133 REG_WRITE(REG_GLOBAL2, 0x0b, 0x9000); 134 135 /* Clear the priority override table. */ 136 for (i = 0; i < 16; i++) 137 REG_WRITE(REG_GLOBAL2, 0x0f, 0x8000 | (i << 8)); 138 139 /* @@@ initialise AVB (22/23) watchdog (27) sdet (29) registers */ 140 141 return 0; 142} 143 144static int mv88e6123_61_65_setup_port(struct dsa_switch *ds, int p) 145{ 146 int addr = REG_PORT(p); 147 u16 val; 148 149 /* MAC Forcing register: don't force link, speed, duplex 150 * or flow control state to any particular values on physical 151 * ports, but force the CPU port and all DSA ports to 1000 Mb/s 152 * full duplex. 153 */ 154 if (dsa_is_cpu_port(ds, p) || ds->dsa_port_mask & (1 << p)) 155 REG_WRITE(addr, 0x01, 0x003e); 156 else 157 REG_WRITE(addr, 0x01, 0x0003); 158 159 /* Do not limit the period of time that this port can be 160 * paused for by the remote end or the period of time that 161 * this port can pause the remote end. 162 */ 163 REG_WRITE(addr, 0x02, 0x0000); 164 165 /* Port Control: disable Drop-on-Unlock, disable Drop-on-Lock, 166 * disable Header mode, enable IGMP/MLD snooping, disable VLAN 167 * tunneling, determine priority by looking at 802.1p and IP 168 * priority fields (IP prio has precedence), and set STP state 169 * to Forwarding. 170 * 171 * If this is the CPU link, use DSA or EDSA tagging depending 172 * on which tagging mode was configured. 173 * 174 * If this is a link to another switch, use DSA tagging mode. 175 * 176 * If this is the upstream port for this switch, enable 177 * forwarding of unknown unicasts and multicasts. 178 */ 179 val = 0x0433; 180 if (dsa_is_cpu_port(ds, p)) { 181 if (ds->dst->tag_protocol == DSA_TAG_PROTO_EDSA) 182 val |= 0x3300; 183 else 184 val |= 0x0100; 185 } 186 if (ds->dsa_port_mask & (1 << p)) 187 val |= 0x0100; 188 if (p == dsa_upstream_port(ds)) 189 val |= 0x000c; 190 REG_WRITE(addr, 0x04, val); 191 192 /* Port Control 2: don't force a good FCS, set the maximum 193 * frame size to 10240 bytes, don't let the switch add or 194 * strip 802.1q tags, don't discard tagged or untagged frames 195 * on this port, do a destination address lookup on all 196 * received packets as usual, disable ARP mirroring and don't 197 * send a copy of all transmitted/received frames on this port 198 * to the CPU. 199 */ 200 REG_WRITE(addr, 0x08, 0x2080); 201 202 /* Egress rate control: disable egress rate control. */ 203 REG_WRITE(addr, 0x09, 0x0001); 204 205 /* Egress rate control 2: disable egress rate control. */ 206 REG_WRITE(addr, 0x0a, 0x0000); 207 208 /* Port Association Vector: when learning source addresses 209 * of packets, add the address to the address database using 210 * a port bitmap that has only the bit for this port set and 211 * the other bits clear. 212 */ 213 REG_WRITE(addr, 0x0b, 1 << p); 214 215 /* Port ATU control: disable limiting the number of address 216 * database entries that this port is allowed to use. 217 */ 218 REG_WRITE(addr, 0x0c, 0x0000); 219 220 /* Priority Override: disable DA, SA and VTU priority override. */ 221 REG_WRITE(addr, 0x0d, 0x0000); 222 223 /* Port Ethertype: use the Ethertype DSA Ethertype value. */ 224 REG_WRITE(addr, 0x0f, ETH_P_EDSA); 225 226 /* Tag Remap: use an identity 802.1p prio -> switch prio 227 * mapping. 228 */ 229 REG_WRITE(addr, 0x18, 0x3210); 230 231 /* Tag Remap 2: use an identity 802.1p prio -> switch prio 232 * mapping. 233 */ 234 REG_WRITE(addr, 0x19, 0x7654); 235 236 return mv88e6xxx_setup_port_common(ds, p); 237} 238 239static int mv88e6123_61_65_setup(struct dsa_switch *ds) 240{ 241 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); 242 int i; 243 int ret; 244 245 ret = mv88e6xxx_setup_common(ds); 246 if (ret < 0) 247 return ret; 248 249 switch (ps->id) { 250 case PORT_SWITCH_ID_6123: 251 ps->num_ports = 3; 252 break; 253 case PORT_SWITCH_ID_6161: 254 case PORT_SWITCH_ID_6165: 255 ps->num_ports = 6; 256 break; 257 default: 258 return -ENODEV; 259 } 260 261 ret = mv88e6xxx_switch_reset(ds, false); 262 if (ret < 0) 263 return ret; 264 265 /* @@@ initialise vtu and atu */ 266 267 ret = mv88e6123_61_65_setup_global(ds); 268 if (ret < 0) 269 return ret; 270 271 for (i = 0; i < ps->num_ports; i++) { 272 ret = mv88e6123_61_65_setup_port(ds, i); 273 if (ret < 0) 274 return ret; 275 } 276 277 return 0; 278} 279 280struct dsa_switch_driver mv88e6123_61_65_switch_driver = { 281 .tag_protocol = DSA_TAG_PROTO_EDSA, 282 .priv_size = sizeof(struct mv88e6xxx_priv_state), 283 .probe = mv88e6123_61_65_probe, 284 .setup = mv88e6123_61_65_setup, 285 .set_addr = mv88e6xxx_set_addr_indirect, 286 .phy_read = mv88e6xxx_phy_read, 287 .phy_write = mv88e6xxx_phy_write, 288 .poll_link = mv88e6xxx_poll_link, 289 .get_strings = mv88e6xxx_get_strings, 290 .get_ethtool_stats = mv88e6xxx_get_ethtool_stats, 291 .get_sset_count = mv88e6xxx_get_sset_count, 292#ifdef CONFIG_NET_DSA_HWMON 293 .get_temp = mv88e6xxx_get_temp, 294#endif 295 .get_regs_len = mv88e6xxx_get_regs_len, 296 .get_regs = mv88e6xxx_get_regs, 297}; 298 299MODULE_ALIAS("platform:mv88e6123"); 300MODULE_ALIAS("platform:mv88e6161"); 301MODULE_ALIAS("platform:mv88e6165"); 302