191da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek/*
291da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek * net/dsa/mv88e6123_61_65.c - Marvell 88e6123/6161/6165 switch chip support
3e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek * Copyright (c) 2008-2009 Marvell Semiconductor
491da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek *
591da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek * This program is free software; you can redistribute it and/or modify
691da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek * it under the terms of the GNU General Public License as published by
791da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek * the Free Software Foundation; either version 2 of the License, or
891da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek * (at your option) any later version.
991da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek */
1091da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
1191da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek#include <linux/list.h>
122bbba277a554431a426e81f37d5c50ab6216c07dPaul Gortmaker#include <linux/module.h>
1391da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek#include <linux/netdevice.h>
1491da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek#include <linux/phy.h>
15c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings#include <net/dsa.h>
1691da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek#include "mv88e6xxx.h"
1791da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
1891da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhekstatic char *mv88e6123_61_65_probe(struct mii_bus *bus, int sw_addr)
1991da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek{
2091da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	int ret;
2191da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
2291da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), 0x03);
2391da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	if (ret >= 0) {
24edd664bbba53f771d4a6d4559ed6e1ff48b46406Chris Healy		if (ret == 0x1212)
25edd664bbba53f771d4a6d4559ed6e1ff48b46406Chris Healy			return "Marvell 88E6123 (A1)";
26edd664bbba53f771d4a6d4559ed6e1ff48b46406Chris Healy		if (ret == 0x1213)
27edd664bbba53f771d4a6d4559ed6e1ff48b46406Chris Healy			return "Marvell 88E6123 (A2)";
28edd664bbba53f771d4a6d4559ed6e1ff48b46406Chris Healy		if ((ret & 0xfff0) == 0x1210)
2991da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek			return "Marvell 88E6123";
30edd664bbba53f771d4a6d4559ed6e1ff48b46406Chris Healy
31edd664bbba53f771d4a6d4559ed6e1ff48b46406Chris Healy		if (ret == 0x1612)
32edd664bbba53f771d4a6d4559ed6e1ff48b46406Chris Healy			return "Marvell 88E6161 (A1)";
33edd664bbba53f771d4a6d4559ed6e1ff48b46406Chris Healy		if (ret == 0x1613)
34edd664bbba53f771d4a6d4559ed6e1ff48b46406Chris Healy			return "Marvell 88E6161 (A2)";
35edd664bbba53f771d4a6d4559ed6e1ff48b46406Chris Healy		if ((ret & 0xfff0) == 0x1610)
3691da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek			return "Marvell 88E6161";
37edd664bbba53f771d4a6d4559ed6e1ff48b46406Chris Healy
38edd664bbba53f771d4a6d4559ed6e1ff48b46406Chris Healy		if (ret == 0x1652)
39edd664bbba53f771d4a6d4559ed6e1ff48b46406Chris Healy			return "Marvell 88E6165 (A1)";
40edd664bbba53f771d4a6d4559ed6e1ff48b46406Chris Healy		if (ret == 0x1653)
41edd664bbba53f771d4a6d4559ed6e1ff48b46406Chris Healy			return "Marvell 88e6165 (A2)";
42edd664bbba53f771d4a6d4559ed6e1ff48b46406Chris Healy		if ((ret & 0xfff0) == 0x1650)
4391da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek			return "Marvell 88E6165";
4491da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	}
4591da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
4691da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	return NULL;
4791da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek}
4891da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
4991da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhekstatic int mv88e6123_61_65_switch_reset(struct dsa_switch *ds)
5091da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek{
5191da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	int i;
5291da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	int ret;
5391da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
5491da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	/*
5591da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * Set all ports to the disabled state.
5691da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 */
5791da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	for (i = 0; i < 8; i++) {
5891da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek		ret = REG_READ(REG_PORT(i), 0x04);
5991da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek		REG_WRITE(REG_PORT(i), 0x04, ret & 0xfffc);
6091da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	}
6191da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
6291da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	/*
6391da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * Wait for transmit queues to drain.
6491da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 */
6591da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	msleep(2);
6691da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
6791da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	/*
6891da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * Reset the switch.
6991da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 */
7091da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	REG_WRITE(REG_GLOBAL, 0x04, 0xc400);
7191da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
7291da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	/*
7391da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * Wait up to one second for reset to complete.
7491da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 */
7591da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	for (i = 0; i < 1000; i++) {
7691da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek		ret = REG_READ(REG_GLOBAL, 0x00);
7791da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek		if ((ret & 0xc800) == 0xc800)
7891da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek			break;
7991da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
8091da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek		msleep(1);
8191da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	}
8291da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	if (i == 1000)
8391da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek		return -ETIMEDOUT;
8491da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
8591da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	return 0;
8691da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek}
8791da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
8891da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhekstatic int mv88e6123_61_65_setup_global(struct dsa_switch *ds)
8991da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek{
9091da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	int ret;
9191da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	int i;
9291da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
9391da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	/*
9491da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * Disable the PHY polling unit (since there won't be any
9591da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * external PHYs to poll), don't discard packets with
9691da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * excessive collisions, and mask all interrupt sources.
9791da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 */
9891da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	REG_WRITE(REG_GLOBAL, 0x04, 0x0000);
9991da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
10091da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	/*
10191da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * Set the default address aging time to 5 minutes, and
10291da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * enable address learn messages to be sent to all message
10391da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * ports.
10491da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 */
10591da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	REG_WRITE(REG_GLOBAL, 0x0a, 0x0148);
10691da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
10791da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	/*
10891da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * Configure the priority mapping registers.
10991da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 */
11091da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	ret = mv88e6xxx_config_prio(ds);
11191da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	if (ret < 0)
11291da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek		return ret;
11391da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
11491da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	/*
115e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	 * Configure the upstream port, and configure the upstream
116e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	 * port as the port to which ingress and egress monitor frames
117e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	 * are to be sent.
11891da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 */
119e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	REG_WRITE(REG_GLOBAL, 0x1a, (dsa_upstream_port(ds) * 0x1110));
12091da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
12191da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	/*
12291da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * Disable remote management for now, and set the switch's
123e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	 * DSA device number.
12491da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 */
125e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	REG_WRITE(REG_GLOBAL, 0x1c, ds->index & 0x1f);
12691da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
12791da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	/*
12891da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * Send all frames with destination addresses matching
12991da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * 01:80:c2:00:00:2x to the CPU port.
13091da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 */
13191da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	REG_WRITE(REG_GLOBAL2, 0x02, 0xffff);
13291da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
13391da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	/*
13491da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * Send all frames with destination addresses matching
13591da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * 01:80:c2:00:00:0x to the CPU port.
13691da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 */
13791da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	REG_WRITE(REG_GLOBAL2, 0x03, 0xffff);
13891da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
13991da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	/*
14091da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * Disable the loopback filter, disable flow control
14191da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * messages, disable flood broadcast override, disable
14291da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * removing of provider tags, disable ATU age violation
14391da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * interrupts, disable tag flow control, force flow
14491da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * control priority to the highest, and send all special
14591da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * multicast frames to the CPU at the highest priority.
14691da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 */
14791da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	REG_WRITE(REG_GLOBAL2, 0x05, 0x00ff);
14891da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
14991da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	/*
150e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	 * Program the DSA routing table.
15191da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 */
152e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	for (i = 0; i < 32; i++) {
153e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek		int nexthop;
154e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek
155e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek		nexthop = 0x1f;
156e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek		if (i != ds->index && i < ds->dst->pd->nr_chips)
157e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek			nexthop = ds->pd->rtable[i] & 0x1f;
158e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek
159e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek		REG_WRITE(REG_GLOBAL2, 0x06, 0x8000 | (i << 8) | nexthop);
160e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	}
16191da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
16291da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	/*
16391da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * Clear all trunk masks.
16491da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 */
16591da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	for (i = 0; i < 8; i++)
16691da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek		REG_WRITE(REG_GLOBAL2, 0x07, 0x8000 | (i << 12) | 0xff);
16791da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
16891da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	/*
16991da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * Clear all trunk mappings.
17091da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 */
17191da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	for (i = 0; i < 16; i++)
17291da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek		REG_WRITE(REG_GLOBAL2, 0x08, 0x8000 | (i << 11));
17391da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
17491da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	/*
17591da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * Disable ingress rate limiting by resetting all ingress
17691da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * rate limit registers to their initial state.
17791da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 */
17891da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	for (i = 0; i < 6; i++)
17991da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek		REG_WRITE(REG_GLOBAL2, 0x09, 0x9000 | (i << 8));
18091da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
18191da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	/*
18291da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * Initialise cross-chip port VLAN table to reset defaults.
18391da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 */
18491da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	REG_WRITE(REG_GLOBAL2, 0x0b, 0x9000);
18591da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
18691da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	/*
18791da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * Clear the priority override table.
18891da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 */
18991da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	for (i = 0; i < 16; i++)
19091da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek		REG_WRITE(REG_GLOBAL2, 0x0f, 0x8000 | (i << 8));
19191da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
19291da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	/* @@@ initialise AVB (22/23) watchdog (27) sdet (29) registers */
19391da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
19491da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	return 0;
19591da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek}
19691da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
19791da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhekstatic int mv88e6123_61_65_setup_port(struct dsa_switch *ds, int p)
19891da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek{
19991da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	int addr = REG_PORT(p);
200e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	u16 val;
20191da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
20291da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	/*
20391da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * MAC Forcing register: don't force link, speed, duplex
204e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	 * or flow control state to any particular values on physical
205e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	 * ports, but force the CPU port and all DSA ports to 1000 Mb/s
206e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	 * full duplex.
20791da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 */
208e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	if (dsa_is_cpu_port(ds, p) || ds->dsa_port_mask & (1 << p))
209e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek		REG_WRITE(addr, 0x01, 0x003e);
210e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	else
211e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek		REG_WRITE(addr, 0x01, 0x0003);
21291da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
21391da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	/*
21491da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * Do not limit the period of time that this port can be
21591da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * paused for by the remote end or the period of time that
21691da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * this port can pause the remote end.
21791da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 */
21891da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	REG_WRITE(addr, 0x02, 0x0000);
21991da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
22091da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	/*
22191da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * Port Control: disable Drop-on-Unlock, disable Drop-on-Lock,
222e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	 * disable Header mode, enable IGMP/MLD snooping, disable VLAN
223e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	 * tunneling, determine priority by looking at 802.1p and IP
224e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	 * priority fields (IP prio has precedence), and set STP state
225e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	 * to Forwarding.
226e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	 *
227e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	 * If this is the CPU link, use DSA or EDSA tagging depending
228e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	 * on which tagging mode was configured.
229e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	 *
230e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	 * If this is a link to another switch, use DSA tagging mode.
231e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	 *
232e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	 * If this is the upstream port for this switch, enable
233e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	 * forwarding of unknown unicasts and multicasts.
23491da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 */
235e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	val = 0x0433;
236e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	if (dsa_is_cpu_port(ds, p)) {
237e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek		if (ds->dst->tag_protocol == htons(ETH_P_EDSA))
238e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek			val |= 0x3300;
239e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek		else
240e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek			val |= 0x0100;
241e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	}
242e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	if (ds->dsa_port_mask & (1 << p))
243e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek		val |= 0x0100;
244e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	if (p == dsa_upstream_port(ds))
245e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek		val |= 0x000c;
246e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	REG_WRITE(addr, 0x04, val);
24791da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
24891da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	/*
24991da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * Port Control 1: disable trunking.  Also, if this is the
25091da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * CPU port, enable learn messages to be sent to this port.
25191da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 */
252e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	REG_WRITE(addr, 0x05, dsa_is_cpu_port(ds, p) ? 0x8000 : 0x0000);
25391da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
25491da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	/*
25591da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * Port based VLAN map: give each port its own address
25691da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * database, allow the CPU port to talk to each of the 'real'
25791da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * ports, and allow each of the 'real' ports to only talk to
258e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	 * the upstream port.
25991da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 */
260e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	val = (p & 0xf) << 12;
261e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	if (dsa_is_cpu_port(ds, p))
262e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek		val |= ds->phys_port_mask;
263e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	else
264e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek		val |= 1 << dsa_upstream_port(ds);
265e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	REG_WRITE(addr, 0x06, val);
26691da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
26791da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	/*
26891da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * Default VLAN ID and priority: don't set a default VLAN
26991da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * ID, and set the default packet priority to zero.
27091da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 */
27191da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	REG_WRITE(addr, 0x07, 0x0000);
27291da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
27391da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	/*
27491da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * Port Control 2: don't force a good FCS, set the maximum
27591da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * frame size to 10240 bytes, don't let the switch add or
27691da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * strip 802.1q tags, don't discard tagged or untagged frames
27791da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * on this port, do a destination address lookup on all
27891da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * received packets as usual, disable ARP mirroring and don't
27991da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * send a copy of all transmitted/received frames on this port
28091da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * to the CPU.
28191da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 */
28291da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	REG_WRITE(addr, 0x08, 0x2080);
28391da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
28491da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	/*
28591da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * Egress rate control: disable egress rate control.
28691da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 */
28791da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	REG_WRITE(addr, 0x09, 0x0001);
28891da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
28991da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	/*
29091da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * Egress rate control 2: disable egress rate control.
29191da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 */
29291da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	REG_WRITE(addr, 0x0a, 0x0000);
29391da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
29491da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	/*
29591da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * Port Association Vector: when learning source addresses
29691da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * of packets, add the address to the address database using
29791da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * a port bitmap that has only the bit for this port set and
29891da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * the other bits clear.
29991da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 */
30091da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	REG_WRITE(addr, 0x0b, 1 << p);
30191da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
30291da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	/*
30391da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * Port ATU control: disable limiting the number of address
30491da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * database entries that this port is allowed to use.
30591da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 */
30691da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	REG_WRITE(addr, 0x0c, 0x0000);
30791da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
30891da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	/*
30991da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * Priorit Override: disable DA, SA and VTU priority override.
31091da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 */
31191da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	REG_WRITE(addr, 0x0d, 0x0000);
31291da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
31391da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	/*
31491da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * Port Ethertype: use the Ethertype DSA Ethertype value.
31591da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 */
31691da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	REG_WRITE(addr, 0x0f, ETH_P_EDSA);
31791da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
31891da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	/*
31991da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * Tag Remap: use an identity 802.1p prio -> switch prio
32091da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * mapping.
32191da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 */
32291da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	REG_WRITE(addr, 0x18, 0x3210);
32391da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
32491da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	/*
32591da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * Tag Remap 2: use an identity 802.1p prio -> switch prio
32691da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * mapping.
32791da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 */
32891da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	REG_WRITE(addr, 0x19, 0x7654);
32991da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
33091da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	return 0;
33191da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek}
33291da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
33391da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhekstatic int mv88e6123_61_65_setup(struct dsa_switch *ds)
33491da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek{
33591da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	struct mv88e6xxx_priv_state *ps = (void *)(ds + 1);
33691da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	int i;
33791da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	int ret;
33891da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
33991da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	mutex_init(&ps->smi_mutex);
34091da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	mutex_init(&ps->stats_mutex);
34191da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
34291da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	ret = mv88e6123_61_65_switch_reset(ds);
34391da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	if (ret < 0)
34491da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek		return ret;
34591da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
34691da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	/* @@@ initialise vtu and atu */
34791da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
34891da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	ret = mv88e6123_61_65_setup_global(ds);
34991da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	if (ret < 0)
35091da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek		return ret;
35191da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
35291da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	for (i = 0; i < 6; i++) {
35391da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek		ret = mv88e6123_61_65_setup_port(ds, i);
35491da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek		if (ret < 0)
35591da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek			return ret;
35691da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	}
35791da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
35891da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	return 0;
35991da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek}
36091da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
36191da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhekstatic int mv88e6123_61_65_port_to_phy_addr(int port)
36291da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek{
36391da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	if (port >= 0 && port <= 4)
36491da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek		return port;
36591da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	return -1;
36691da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek}
36791da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
36891da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhekstatic int
36991da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhekmv88e6123_61_65_phy_read(struct dsa_switch *ds, int port, int regnum)
37091da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek{
37191da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	int addr = mv88e6123_61_65_port_to_phy_addr(port);
37291da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	return mv88e6xxx_phy_read(ds, addr, regnum);
37391da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek}
37491da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
37591da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhekstatic int
37691da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhekmv88e6123_61_65_phy_write(struct dsa_switch *ds,
37791da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek			      int port, int regnum, u16 val)
37891da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek{
37991da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	int addr = mv88e6123_61_65_port_to_phy_addr(port);
38091da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	return mv88e6xxx_phy_write(ds, addr, regnum, val);
38191da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek}
38291da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
38391da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhekstatic struct mv88e6xxx_hw_stat mv88e6123_61_65_hw_stats[] = {
38491da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	{ "in_good_octets", 8, 0x00, },
38591da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	{ "in_bad_octets", 4, 0x02, },
38691da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	{ "in_unicast", 4, 0x04, },
38791da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	{ "in_broadcasts", 4, 0x06, },
38891da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	{ "in_multicasts", 4, 0x07, },
38991da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	{ "in_pause", 4, 0x16, },
39091da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	{ "in_undersize", 4, 0x18, },
39191da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	{ "in_fragments", 4, 0x19, },
39291da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	{ "in_oversize", 4, 0x1a, },
39391da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	{ "in_jabber", 4, 0x1b, },
39491da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	{ "in_rx_error", 4, 0x1c, },
39591da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	{ "in_fcs_error", 4, 0x1d, },
39691da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	{ "out_octets", 8, 0x0e, },
39791da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	{ "out_unicast", 4, 0x10, },
39891da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	{ "out_broadcasts", 4, 0x13, },
39991da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	{ "out_multicasts", 4, 0x12, },
40091da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	{ "out_pause", 4, 0x15, },
40191da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	{ "excessive", 4, 0x11, },
40291da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	{ "collisions", 4, 0x1e, },
40391da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	{ "deferred", 4, 0x05, },
40491da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	{ "single", 4, 0x14, },
40591da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	{ "multiple", 4, 0x17, },
40691da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	{ "out_fcs_error", 4, 0x03, },
40791da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	{ "late", 4, 0x1f, },
40891da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	{ "hist_64bytes", 4, 0x08, },
40991da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	{ "hist_65_127bytes", 4, 0x09, },
41091da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	{ "hist_128_255bytes", 4, 0x0a, },
41191da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	{ "hist_256_511bytes", 4, 0x0b, },
41291da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	{ "hist_512_1023bytes", 4, 0x0c, },
41391da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	{ "hist_1024_max_bytes", 4, 0x0d, },
41491da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek};
41591da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
41691da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhekstatic void
41791da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhekmv88e6123_61_65_get_strings(struct dsa_switch *ds, int port, uint8_t *data)
41891da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek{
41991da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	mv88e6xxx_get_strings(ds, ARRAY_SIZE(mv88e6123_61_65_hw_stats),
42091da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek			      mv88e6123_61_65_hw_stats, port, data);
42191da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek}
42291da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
42391da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhekstatic void
42491da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhekmv88e6123_61_65_get_ethtool_stats(struct dsa_switch *ds,
42591da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek				  int port, uint64_t *data)
42691da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek{
42791da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	mv88e6xxx_get_ethtool_stats(ds, ARRAY_SIZE(mv88e6123_61_65_hw_stats),
42891da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek				    mv88e6123_61_65_hw_stats, port, data);
42991da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek}
43091da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
43191da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhekstatic int mv88e6123_61_65_get_sset_count(struct dsa_switch *ds)
43291da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek{
43391da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	return ARRAY_SIZE(mv88e6123_61_65_hw_stats);
43491da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek}
43591da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
43698e673080bd90b9338428be92dd3597798aac3edBen Hutchingsstruct dsa_switch_driver mv88e6123_61_65_switch_driver = {
43709640e6365c679b5642b1c41b6d7078f51689ddfHarvey Harrison	.tag_protocol		= cpu_to_be16(ETH_P_EDSA),
43891da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	.priv_size		= sizeof(struct mv88e6xxx_priv_state),
43991da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	.probe			= mv88e6123_61_65_probe,
44091da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	.setup			= mv88e6123_61_65_setup,
44191da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	.set_addr		= mv88e6xxx_set_addr_indirect,
44291da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	.phy_read		= mv88e6123_61_65_phy_read,
44391da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	.phy_write		= mv88e6123_61_65_phy_write,
44491da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	.poll_link		= mv88e6xxx_poll_link,
44591da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	.get_strings		= mv88e6123_61_65_get_strings,
44691da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	.get_ethtool_stats	= mv88e6123_61_65_get_ethtool_stats,
44791da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	.get_sset_count		= mv88e6123_61_65_get_sset_count,
44891da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek};
4493d825ede8c79a4799a6a3c34719551c7c1908b96Ben Hutchings
4503d825ede8c79a4799a6a3c34719551c7c1908b96Ben HutchingsMODULE_ALIAS("platform:mv88e6123");
4513d825ede8c79a4799a6a3c34719551c7c1908b96Ben HutchingsMODULE_ALIAS("platform:mv88e6161");
4523d825ede8c79a4799a6a3c34719551c7c1908b96Ben HutchingsMODULE_ALIAS("platform:mv88e6165");
453