mv88e6131.c 8.3 KB
Newer Older
1
/*
2 3
 * net/dsa/mv88e6131.c - Marvell 88e6095/6095f/6131 switch chip support
 * Copyright (c) 2008-2009 Marvell Semiconductor
4 5 6 7 8 9 10
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */

11 12
#include <linux/delay.h>
#include <linux/jiffies.h>
13
#include <linux/list.h>
14
#include <linux/module.h>
15 16
#include <linux/netdevice.h>
#include <linux/phy.h>
17
#include <net/dsa.h>
18 19
#include "mv88e6xxx.h"

20
static char *mv88e6131_probe(struct device *host_dev, int sw_addr)
21
{
22
	struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev);
23 24
	int ret;

25 26 27
	if (bus == NULL)
		return NULL;

28 29
	ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), 0x03);
	if (ret >= 0) {
30 31 32
		int ret_masked = ret & 0xfff0;

		if (ret_masked == ID_6085)
33
			return "Marvell 88E6085";
34
		if (ret_masked == ID_6095)
35
			return "Marvell 88E6095/88E6095F";
36 37 38
		if (ret == ID_6131_B2)
			return "Marvell 88E6131 (B2)";
		if (ret_masked == ID_6131)
39 40 41 42 43 44 45 46 47 48 49
			return "Marvell 88E6131";
	}

	return NULL;
}

static int mv88e6131_setup_global(struct dsa_switch *ds)
{
	int ret;
	int i;

50
	/* Enable the PHY polling unit, don't discard packets with
51 52 53 54 55 56
	 * excessive collisions, use a weighted fair queueing scheme
	 * to arbitrate between packet queues, set the maximum frame
	 * size to 1632, and mask all interrupt sources.
	 */
	REG_WRITE(REG_GLOBAL, 0x04, 0x4400);

57
	/* Set the default address aging time to 5 minutes, and
58 59 60 61 62
	 * enable address learn messages to be sent to all message
	 * ports.
	 */
	REG_WRITE(REG_GLOBAL, 0x0a, 0x0148);

63
	/* Configure the priority mapping registers. */
64 65 66 67
	ret = mv88e6xxx_config_prio(ds);
	if (ret < 0)
		return ret;

68
	/* Set the VLAN ethertype to 0x8100. */
69 70
	REG_WRITE(REG_GLOBAL, 0x19, 0x8100);

71
	/* Disable ARP mirroring, and configure the upstream port as
72 73
	 * the port to which ingress and egress monitor frames are to
	 * be sent.
74
	 */
75
	REG_WRITE(REG_GLOBAL, 0x1a, (dsa_upstream_port(ds) * 0x1100) | 0x00f0);
76

77
	/* Disable cascade port functionality unless this device
78
	 * is used in a cascade configuration, and set the switch's
79
	 * DSA device number.
80
	 */
81 82 83 84
	if (ds->dst->pd->nr_chips > 1)
		REG_WRITE(REG_GLOBAL, 0x1c, 0xf000 | (ds->index & 0x1f));
	else
		REG_WRITE(REG_GLOBAL, 0x1c, 0xe000 | (ds->index & 0x1f));
85

86
	/* Send all frames with destination addresses matching
87 88 89 90
	 * 01:80:c2:00:00:0x to the CPU port.
	 */
	REG_WRITE(REG_GLOBAL2, 0x03, 0xffff);

91
	/* Ignore removed tag data on doubly tagged packets, disable
92 93
	 * flow control messages, force flow control priority to the
	 * highest, and send all special multicast frames to the CPU
L
Lucas De Marchi 已提交
94
	 * port at the highest priority.
95 96 97
	 */
	REG_WRITE(REG_GLOBAL2, 0x05, 0x00ff);

98
	/* Program the DSA routing table. */
99 100 101 102
	for (i = 0; i < 32; i++) {
		int nexthop;

		nexthop = 0x1f;
103 104
		if (ds->pd->rtable &&
		    i != ds->index && i < ds->dst->pd->nr_chips)
105 106 107 108
			nexthop = ds->pd->rtable[i] & 0x1f;

		REG_WRITE(REG_GLOBAL2, 0x06, 0x8000 | (i << 8) | nexthop);
	}
109

110
	/* Clear all trunk masks. */
111
	for (i = 0; i < 8; i++)
112
		REG_WRITE(REG_GLOBAL2, 0x07, 0x8000 | (i << 12) | 0x7ff);
113

114
	/* Clear all trunk mappings. */
115 116 117
	for (i = 0; i < 16; i++)
		REG_WRITE(REG_GLOBAL2, 0x08, 0x8000 | (i << 11));

118
	/* Force the priority of IGMP/MLD snoop frames and ARP frames
119 120 121 122 123 124 125 126 127
	 * to the highest setting.
	 */
	REG_WRITE(REG_GLOBAL2, 0x0f, 0x00ff);

	return 0;
}

static int mv88e6131_setup_port(struct dsa_switch *ds, int p)
{
128
	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
129
	int addr = REG_PORT(p);
130
	u16 val;
131

132
	/* MAC Forcing register: don't force link, speed, duplex
133
	 * or flow control state to any particular values on physical
134
	 * ports, but force the CPU port and all DSA ports to 1000 Mb/s
135
	 * (100 Mb/s on 6085) full duplex.
136
	 */
137
	if (dsa_is_cpu_port(ds, p) || ds->dsa_port_mask & (1 << p))
138 139 140 141
		if (ps->id == ID_6085)
			REG_WRITE(addr, 0x01, 0x003d); /* 100 Mb/s */
		else
			REG_WRITE(addr, 0x01, 0x003e); /* 1000 Mb/s */
142 143
	else
		REG_WRITE(addr, 0x01, 0x0003);
144

145
	/* Port Control: disable Core Tag, disable Drop-on-Lock,
146 147 148 149
	 * transmit frames unmodified, disable Header mode,
	 * enable IGMP/MLD snoop, disable DoubleTag, disable VLAN
	 * tunneling, determine priority by looking at 802.1p and
	 * IP priority fields (IP prio has precedence), and set STP
150 151 152 153 154 155 156 157
	 * state to Forwarding.
	 *
	 * If this is the upstream port for this switch, enable
	 * forwarding of unknown unicasts, and enable DSA tagging
	 * mode.
	 *
	 * If this is the link to another switch, use DSA tagging
	 * mode, but do not enable forwarding of unknown unicasts.
158
	 */
159
	val = 0x0433;
160
	if (p == dsa_upstream_port(ds)) {
161
		val |= 0x0104;
162
		/* On 6085, unknown multicast forward is controlled
163 164 165 166 167
		 * here rather than in Port Control 2 register.
		 */
		if (ps->id == ID_6085)
			val |= 0x0008;
	}
168 169 170
	if (ds->dsa_port_mask & (1 << p))
		val |= 0x0100;
	REG_WRITE(addr, 0x04, val);
171

172
	/* Port Control 2: don't force a good FCS, don't use
173 174 175 176 177 178
	 * VLAN-based, source address-based or destination
	 * address-based priority overrides, don't let the switch
	 * add or strip 802.1q tags, don't discard tagged or
	 * untagged frames on this port, do a destination address
	 * lookup on received packets as usual, don't send a copy
	 * of all transmitted/received frames on this port to the
179 180 181 182
	 * CPU, and configure the upstream port number.
	 *
	 * If this is the upstream port for this switch, enable
	 * forwarding of unknown multicast addresses.
183
	 */
184
	if (ps->id == ID_6085)
185
		/* on 6085, bits 3:0 are reserved, bit 6 control ARP
186 187 188 189 190 191 192 193 194 195
		 * mirroring, and multicast forward is handled in
		 * Port Control register.
		 */
		REG_WRITE(addr, 0x08, 0x0080);
	else {
		val = 0x0080 | dsa_upstream_port(ds);
		if (p == dsa_upstream_port(ds))
			val |= 0x0040;
		REG_WRITE(addr, 0x08, val);
	}
196

197
	/* Rate Control: disable ingress rate limiting. */
198 199
	REG_WRITE(addr, 0x09, 0x0000);

200
	/* Rate Control 2: disable egress rate limiting. */
201 202
	REG_WRITE(addr, 0x0a, 0x0000);

203
	/* Port Association Vector: when learning source addresses
204 205 206 207 208 209
	 * of packets, add the address to the address database using
	 * a port bitmap that has only the bit for this port set and
	 * the other bits clear.
	 */
	REG_WRITE(addr, 0x0b, 1 << p);

210
	/* Tag Remap: use an identity 802.1p prio -> switch prio
211 212 213 214
	 * mapping.
	 */
	REG_WRITE(addr, 0x18, 0x3210);

215
	/* Tag Remap 2: use an identity 802.1p prio -> switch prio
216 217 218 219
	 * mapping.
	 */
	REG_WRITE(addr, 0x19, 0x7654);

220
	return mv88e6xxx_setup_port_common(ds, p);
221 222 223 224
}

static int mv88e6131_setup(struct dsa_switch *ds)
{
225
	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
226 227 228
	int i;
	int ret;

229 230 231
	ret = mv88e6xxx_setup_common(ds);
	if (ret < 0)
		return ret;
232

233
	mv88e6xxx_ppu_state_init(ds);
234

235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
	switch (ps->id) {
	case ID_6085:
		ps->num_ports = 10;
		break;
	case ID_6095:
		ps->num_ports = 11;
		break;
	case ID_6131:
	case ID_6131_B2:
		ps->num_ports = 8;
		break;
	default:
		return -ENODEV;
	}

250
	ret = mv88e6xxx_switch_reset(ds, false);
251 252 253 254 255 256 257 258 259
	if (ret < 0)
		return ret;

	/* @@@ initialise vtu and atu */

	ret = mv88e6131_setup_global(ds);
	if (ret < 0)
		return ret;

260
	for (i = 0; i < ps->num_ports; i++) {
261 262 263 264 265 266 267 268
		ret = mv88e6131_setup_port(ds, i);
		if (ret < 0)
			return ret;
	}

	return 0;
}

269
static int mv88e6131_port_to_phy_addr(struct dsa_switch *ds, int port)
270
{
271 272 273
	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);

	if (port >= 0 && port < ps->num_ports)
274
		return port;
275 276

	return -EINVAL;
277 278 279 280 281
}

static int
mv88e6131_phy_read(struct dsa_switch *ds, int port, int regnum)
{
282 283 284 285 286
	int addr = mv88e6131_port_to_phy_addr(ds, port);

	if (addr < 0)
		return addr;

287 288 289 290 291 292 293
	return mv88e6xxx_phy_read_ppu(ds, addr, regnum);
}

static int
mv88e6131_phy_write(struct dsa_switch *ds,
			      int port, int regnum, u16 val)
{
294 295 296 297 298
	int addr = mv88e6131_port_to_phy_addr(ds, port);

	if (addr < 0)
		return addr;

299 300 301
	return mv88e6xxx_phy_write_ppu(ds, addr, regnum, val);
}

302
struct dsa_switch_driver mv88e6131_switch_driver = {
303
	.tag_protocol		= DSA_TAG_PROTO_DSA,
304 305 306 307 308 309 310
	.priv_size		= sizeof(struct mv88e6xxx_priv_state),
	.probe			= mv88e6131_probe,
	.setup			= mv88e6131_setup,
	.set_addr		= mv88e6xxx_set_addr_direct,
	.phy_read		= mv88e6131_phy_read,
	.phy_write		= mv88e6131_phy_write,
	.poll_link		= mv88e6xxx_poll_link,
311 312 313
	.get_strings		= mv88e6xxx_get_strings,
	.get_ethtool_stats	= mv88e6xxx_get_ethtool_stats,
	.get_sset_count		= mv88e6xxx_get_sset_count,
314
};
315 316 317 318 319

MODULE_ALIAS("platform:mv88e6085");
MODULE_ALIAS("platform:mv88e6095");
MODULE_ALIAS("platform:mv88e6095f");
MODULE_ALIAS("platform:mv88e6131");