History

Merge branch 'dsa-mv88e6xxx-monolithic'

Vivien Didelot says: ==================== net: dsa: mv88e6xxx: turn into monolithic driver This patchset merges all mv88e6* drivers supported by the shared mv88e6xxx code into a single mv88e6xxx DSA switch driver. Some flags are added to describe the capabilities of a switch model, such as the presence of a PPU, EEPROM, some old or new registers, etc. First these flags are used to conditionally support the same set of functions in every driver, then specific driver files are removed in favor of the common mv88e6xxx driver. Only the merge of driver specific setup code assumes a few differences. If these differences such as frames priorities are really needed for some models, they can easily be brought back in a future patch. Some inconsistencies might show up, such as the need for MV88E6XXX_FLAG_PPU and MV88E6XXX_FLAG_PPU_ACTIVE flags. But this patchset does not aim to fix them yet. A future patch can do that if they end up being unwanted. The patchset has been tested on interconnected 88E6352 and 88E6185. Changes v1 -> v2: - add missing MV88E6XXX_FLAG_EEPROM flag checks - remove a few remaining _ prefixes - remove MV88E6XXX_FLAG_CORE_TAG_TYPE which is a specific default Changes RFC -> v1: - introduce flags in a separate patch - do not refactor anything yet - do not add new functions prefixed with _ - drop packet discarding and mentioned tested platforms - factorize family flags - update text for NET_DSA_MV88E6XXX Kconfig entry ====================

David S. Miller committed 10 years ago

Commit e26522c2 parents 908578e f81ec9013 files · +899 −1264Browse files

Unified · Split

13 files
  1. arch/arm/configs/multi_v5_defconfig +1 −4
  2. arch/arm/configs/mvebu_v7_defconfig +1 −1
  3. arch/arm/configs/orion5x_defconfig +1 −2
  4. arch/tile/configs/tilegx_defconfig +1 −2
  5. arch/tile/configs/tilepro_defconfig +1 −2
  6. drivers/net/dsa/Kconfig +4 −41
  7. drivers/net/dsa/Makefile +1 −14
  8. drivers/net/dsa/mv88e6123.c +0 −130
  9. drivers/net/dsa/mv88e6131.c +0 −204
  10. drivers/net/dsa/mv88e6171.c +0 −151
  11. drivers/net/dsa/mv88e6352.c +0 −377
  12. drivers/net/dsa/mv88e6xxx.c +733 −253
  13. drivers/net/dsa/mv88e6xxx.h +156 −83
arch/arm/configs/multi_v5_defconfig+1−4
@@ -91,10 +91,7 @@ CONFIG_SATA_AHCI=y · 90 unmodified lines
9191 CONFIG_SATA_MV=y
9292 CONFIG_NETDEVICES=y
9393 CONFIG_NET_DSA_MV88E6060=y
94−CONFIG_NET_DSA_MV88E6131=y
95−CONFIG_NET_DSA_MV88E6123=y
96−CONFIG_NET_DSA_MV88E6171=y
97−CONFIG_NET_DSA_MV88E6352=y
94+CONFIG_NET_DSA_MV88E6XXX=y
9895 CONFIG_MV643XX_ETH=y
9996 CONFIG_R8169=y
10097 CONFIG_MARVELL_PHY=y
arch/arm/configs/mvebu_v7_defconfig+1−1
@@ -66,7 +66,7 @@ CONFIG_SATA_AHCI=y · 65 unmodified lines
6666 CONFIG_AHCI_MVEBU=y
6767 CONFIG_SATA_MV=y
6868 CONFIG_NETDEVICES=y
69−CONFIG_NET_DSA_MV88E6171=y
69+CONFIG_NET_DSA_MV88E6XXX=y
7070 CONFIG_MV643XX_ETH=y
7171 CONFIG_MVNETA=y
7272 CONFIG_MVPP2=y
arch/arm/configs/orion5x_defconfig+1−2
@@ -85,8 +85,7 @@ CONFIG_ATA=y · 84 unmodified lines
8585 CONFIG_SATA_MV=y
8686 CONFIG_NETDEVICES=y
8787 CONFIG_MII=y
88−CONFIG_NET_DSA_MV88E6131=y
89−CONFIG_NET_DSA_MV88E6123=y
88+CONFIG_NET_DSA_MV88E6XXX=y
9089 CONFIG_MV643XX_ETH=y
9190 CONFIG_MARVELL_PHY=y
9291 # CONFIG_INPUT_MOUSEDEV is not set
arch/tile/configs/tilegx_defconfig+1−2
@@ -221,8 +221,7 @@ CONFIG_NETCONSOLE_DYNAMIC=y · 220 unmodified lines
221221 CONFIG_TUN=y
222222 CONFIG_VETH=m
223223 CONFIG_NET_DSA_MV88E6060=y
224−CONFIG_NET_DSA_MV88E6131=y
225−CONFIG_NET_DSA_MV88E6123=y
224+CONFIG_NET_DSA_MV88E6XXX=y
226225 CONFIG_SKY2=y
227226 CONFIG_PTP_1588_CLOCK_TILEGX=y
228227 # CONFIG_WLAN is not set
arch/tile/configs/tilepro_defconfig+1−2
@@ -340,8 +340,7 @@ CONFIG_NETCONSOLE_DYNAMIC=y · 339 unmodified lines
340340 CONFIG_TUN=y
341341 CONFIG_VETH=m
342342 CONFIG_NET_DSA_MV88E6060=y
343−CONFIG_NET_DSA_MV88E6131=y
344−CONFIG_NET_DSA_MV88E6123=y
343+CONFIG_NET_DSA_MV88E6XXX=y
345344 # CONFIG_NET_VENDOR_3COM is not set
346345 CONFIG_E1000E=y
347346 # CONFIG_WLAN is not set
drivers/net/dsa/Kconfig+4−41
@@ -1,10 +1,6 @@
11 menu "Distributed Switch Architecture drivers"
22 depends on HAVE_NET_DSA
33
4−config NET_DSA_MV88E6XXX
5− tristate
6− default n
7−
84 config NET_DSA_MV88E6060
95 tristate "Marvell 88E6060 ethernet switch chip support"
106 depends on NET_DSA
@@ -13,46 +9,13 @@ config NET_DSA_MV88E6060 · 2 unmodified lines
139 This enables support for the Marvell 88E6060 ethernet switch
1410 chip.
1511
16−config NET_DSA_MV88E6XXX_NEED_PPU
17− bool
18− default n
19−
20−config NET_DSA_MV88E6131
21− tristate "Marvell 88E6085/6095/6095F/6131 ethernet switch chip support"
22− depends on NET_DSA
23− select NET_DSA_MV88E6XXX
24− select NET_DSA_MV88E6XXX_NEED_PPU
25− select NET_DSA_TAG_DSA
26− ---help---
27− This enables support for the Marvell 88E6085/6095/6095F/6131
28− ethernet switch chips.
29−
30−config NET_DSA_MV88E6123
31− tristate "Marvell 88E6123/6161/6165 ethernet switch chip support"
32− depends on NET_DSA
33− select NET_DSA_MV88E6XXX
34− select NET_DSA_TAG_EDSA
35− ---help---
36− This enables support for the Marvell 88E6123/6161/6165
37− ethernet switch chips.
38−
39−config NET_DSA_MV88E6171
40− tristate "Marvell 88E6171/6175/6350/6351 ethernet switch chip support"
41− depends on NET_DSA
42− select NET_DSA_MV88E6XXX
43− select NET_DSA_TAG_EDSA
44− ---help---
45− This enables support for the Marvell 88E6171/6175/6350/6351
46− ethernet switches chips.
47−
48−config NET_DSA_MV88E6352
49− tristate "Marvell 88E6172/6176/6320/6321/6352 ethernet switch chip support"
12+config NET_DSA_MV88E6XXX
13+ tristate "Marvell 88E6xxx Ethernet switch chip support"
5014 depends on NET_DSA
51− select NET_DSA_MV88E6XXX
5215 select NET_DSA_TAG_EDSA
5316 ---help---
54− This enables support for the Marvell 88E6172, 88E6176, 88E6320,
55− 88E6321 and 88E6352 ethernet switch chips.
17+ This enables support for most of the Marvell 88E6xxx models of
18+ Ethernet switch chips, except 88E6060.
5619
5720 config NET_DSA_BCM_SF2
5821 tristate "Broadcom Starfighter 2 Ethernet switch support"
drivers/net/dsa/Makefile+1−14
@@ -1,16 +1,3 @@
11 obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o
2−obj-$(CONFIG_NET_DSA_MV88E6XXX) += mv88e6xxx_drv.o
3−mv88e6xxx_drv-y += mv88e6xxx.o
4−ifdef CONFIG_NET_DSA_MV88E6123
5−mv88e6xxx_drv-y += mv88e6123.o
6−endif
7−ifdef CONFIG_NET_DSA_MV88E6131
8−mv88e6xxx_drv-y += mv88e6131.o
9−endif
10−ifdef CONFIG_NET_DSA_MV88E6352
11−mv88e6xxx_drv-y += mv88e6352.o
12−endif
13−ifdef CONFIG_NET_DSA_MV88E6171
14−mv88e6xxx_drv-y += mv88e6171.o
15−endif
2+obj-$(CONFIG_NET_DSA_MV88E6XXX) += mv88e6xxx.o
163 obj-$(CONFIG_NET_DSA_BCM_SF2) += bcm_sf2.o
drivers/net/dsa/mv88e6123.c+0−130
@@ -1,130 +0,0 @@
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−
20−static const struct mv88e6xxx_info mv88e6123_table[] = {
21− {
22− .prod_num = PORT_SWITCH_ID_PROD_NUM_6123,
23− .family = MV88E6XXX_FAMILY_6165,
24− .name = "Marvell 88E6123",
25− .num_databases = 4096,
26− .num_ports = 3,
27− }, {
28− .prod_num = PORT_SWITCH_ID_PROD_NUM_6161,
29− .family = MV88E6XXX_FAMILY_6165,
30− .name = "Marvell 88E6161",
31− .num_databases = 4096,
32− .num_ports = 6,
33− }, {
34− .prod_num = PORT_SWITCH_ID_PROD_NUM_6165,
35− .family = MV88E6XXX_FAMILY_6165,
36− .name = "Marvell 88E6165",
37− .num_databases = 4096,
38− .num_ports = 6,
39− }
40−};
41−
42−static const char *mv88e6123_drv_probe(struct device *dsa_dev,
43− struct device *host_dev, int sw_addr,
44− void **priv)
45−{
46− return mv88e6xxx_drv_probe(dsa_dev, host_dev, sw_addr, priv,
47− mv88e6123_table,
48− ARRAY_SIZE(mv88e6123_table));
49−}
50−
51−static int mv88e6123_setup_global(struct dsa_switch *ds)
52−{
53− struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
54− u32 upstream_port = dsa_upstream_port(ds);
55− int ret;
56− u32 reg;
57−
58− ret = mv88e6xxx_setup_global(ds);
59− if (ret)
60− return ret;
61−
62− /* Disable the PHY polling unit (since there won't be any
63− * external PHYs to poll), don't discard packets with
64− * excessive collisions, and mask all interrupt sources.
65− */
66− ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL, 0x0000);
67− if (ret)
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 = upstream_port << GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT |
75− upstream_port << GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT |
76− upstream_port << GLOBAL_MONITOR_CONTROL_ARP_SHIFT;
77− ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_MONITOR_CONTROL, reg);
78− if (ret)
79− return ret;
80−
81− /* Disable remote management for now, and set the switch's
82− * DSA device number.
83− */
84− return mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL_2,
85− ds->index & 0x1f);
86−}
87−
88−static int mv88e6123_setup(struct dsa_switch *ds)
89−{
90− struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
91− int ret;
92−
93− ps->ds = ds;
94−
95− ret = mv88e6xxx_setup_common(ps);
96− if (ret < 0)
97− return ret;
98−
99− ret = mv88e6xxx_switch_reset(ps, false);
100− if (ret < 0)
101− return ret;
102−
103− ret = mv88e6123_setup_global(ds);
104− if (ret < 0)
105− return ret;
106−
107− return mv88e6xxx_setup_ports(ds);
108−}
109−
110−struct dsa_switch_driver mv88e6123_switch_driver = {
111− .tag_protocol = DSA_TAG_PROTO_EDSA,
112− .probe = mv88e6123_drv_probe,
113− .setup = mv88e6123_setup,
114− .set_addr = mv88e6xxx_set_addr_indirect,
115− .phy_read = mv88e6xxx_phy_read,
116− .phy_write = mv88e6xxx_phy_write,
117− .get_strings = mv88e6xxx_get_strings,
118− .get_ethtool_stats = mv88e6xxx_get_ethtool_stats,
119− .get_sset_count = mv88e6xxx_get_sset_count,
120− .adjust_link = mv88e6xxx_adjust_link,
121−#ifdef CONFIG_NET_DSA_HWMON
122− .get_temp = mv88e6xxx_get_temp,
123−#endif
124− .get_regs_len = mv88e6xxx_get_regs_len,
125− .get_regs = mv88e6xxx_get_regs,
126−};
127−
128−MODULE_ALIAS("platform:mv88e6123");
129−MODULE_ALIAS("platform:mv88e6161");
130−MODULE_ALIAS("platform:mv88e6165");
drivers/net/dsa/mv88e6131.c+0−204
@@ -1,204 +0,0 @@
1−/*
2− * net/dsa/mv88e6131.c - Marvell 88e6095/6095f/6131 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−
20−static const struct mv88e6xxx_info mv88e6131_table[] = {
21− {
22− .prod_num = PORT_SWITCH_ID_PROD_NUM_6095,
23− .family = MV88E6XXX_FAMILY_6095,
24− .name = "Marvell 88E6095/88E6095F",
25− .num_databases = 256,
26− .num_ports = 11,
27− }, {
28− .prod_num = PORT_SWITCH_ID_PROD_NUM_6085,
29− .family = MV88E6XXX_FAMILY_6097,
30− .name = "Marvell 88E6085",
31− .num_databases = 4096,
32− .num_ports = 10,
33− }, {
34− .prod_num = PORT_SWITCH_ID_PROD_NUM_6131,
35− .family = MV88E6XXX_FAMILY_6185,
36− .name = "Marvell 88E6131",
37− .num_databases = 256,
38− .num_ports = 8,
39− }, {
40− .prod_num = PORT_SWITCH_ID_PROD_NUM_6185,
41− .family = MV88E6XXX_FAMILY_6185,
42− .name = "Marvell 88E6185",
43− .num_databases = 256,
44− .num_ports = 10,
45− }
46−};
47−
48−static const char *mv88e6131_drv_probe(struct device *dsa_dev,
49− struct device *host_dev, int sw_addr,
50− void **priv)
51−{
52− return mv88e6xxx_drv_probe(dsa_dev, host_dev, sw_addr, priv,
53− mv88e6131_table,
54− ARRAY_SIZE(mv88e6131_table));
55−}
56−
57−static int mv88e6131_setup_global(struct dsa_switch *ds)
58−{
59− struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
60− u32 upstream_port = dsa_upstream_port(ds);
61− int ret;
62− u32 reg;
63−
64− ret = mv88e6xxx_setup_global(ds);
65− if (ret)
66− return ret;
67−
68− /* Enable the PHY polling unit, don't discard packets with
69− * excessive collisions, use a weighted fair queueing scheme
70− * to arbitrate between packet queues, set the maximum frame
71− * size to 1632, and mask all interrupt sources.
72− */
73− ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL,
74− GLOBAL_CONTROL_PPU_ENABLE |
75− GLOBAL_CONTROL_MAX_FRAME_1632);
76− if (ret)
77− return ret;
78−
79− /* Set the VLAN ethertype to 0x8100. */
80− ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CORE_TAG_TYPE, 0x8100);
81− if (ret)
82− return ret;
83−
84− /* Disable ARP mirroring, and configure the upstream port as
85− * the port to which ingress and egress monitor frames are to
86− * be sent.
87− */
88− reg = upstream_port << GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT |
89− upstream_port << GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT |
90− GLOBAL_MONITOR_CONTROL_ARP_DISABLED;
91− ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_MONITOR_CONTROL, reg);
92− if (ret)
93− return ret;
94−
95− /* Disable cascade port functionality unless this device
96− * is used in a cascade configuration, and set the switch's
97− * DSA device number.
98− */
99− if (ds->dst->pd->nr_chips > 1)
100− ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL_2,
101− GLOBAL_CONTROL_2_MULTIPLE_CASCADE |
102− (ds->index & 0x1f));
103− else
104− ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL_2,
105− GLOBAL_CONTROL_2_NO_CASCADE |
106− (ds->index & 0x1f));
107− if (ret)
108− return ret;
109−
110− /* Force the priority of IGMP/MLD snoop frames and ARP frames
111− * to the highest setting.
112− */
113− return mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_PRIO_OVERRIDE,
114− GLOBAL2_PRIO_OVERRIDE_FORCE_SNOOP |
115− 7 << GLOBAL2_PRIO_OVERRIDE_SNOOP_SHIFT |
116− GLOBAL2_PRIO_OVERRIDE_FORCE_ARP |
117− 7 << GLOBAL2_PRIO_OVERRIDE_ARP_SHIFT);
118−}
119−
120−static int mv88e6131_setup(struct dsa_switch *ds)
121−{
122− struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
123− int ret;
124−
125− ps->ds = ds;
126−
127− ret = mv88e6xxx_setup_common(ps);
128− if (ret < 0)
129− return ret;
130−
131− mv88e6xxx_ppu_state_init(ps);
132−
133− ret = mv88e6xxx_switch_reset(ps, false);
134− if (ret < 0)
135− return ret;
136−
137− ret = mv88e6131_setup_global(ds);
138− if (ret < 0)
139− return ret;
140−
141− return mv88e6xxx_setup_ports(ds);
142−}
143−
144−static int mv88e6131_port_to_phy_addr(struct dsa_switch *ds, int port)
145−{
146− struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
147−
148− if (port >= 0 && port < ps->info->num_ports)
149− return port;
150−
151− return -EINVAL;
152−}
153−
154−static int
155−mv88e6131_phy_read(struct dsa_switch *ds, int port, int regnum)
156−{
157− int addr = mv88e6131_port_to_phy_addr(ds, port);
158−
159− if (addr < 0)
160− return addr;
161−
162− return mv88e6xxx_phy_read_ppu(ds, addr, regnum);
163−}
164−
165−static int
166−mv88e6131_phy_write(struct dsa_switch *ds,
167− int port, int regnum, u16 val)
168−{
169− int addr = mv88e6131_port_to_phy_addr(ds, port);
170−
171− if (addr < 0)
172− return addr;
173−
174− return mv88e6xxx_phy_write_ppu(ds, addr, regnum, val);
175−}
176−
177−struct dsa_switch_driver mv88e6131_switch_driver = {
178− .tag_protocol = DSA_TAG_PROTO_DSA,
179− .probe = mv88e6131_drv_probe,
180− .setup = mv88e6131_setup,
181− .set_addr = mv88e6xxx_set_addr_direct,
182− .phy_read = mv88e6131_phy_read,
183− .phy_write = mv88e6131_phy_write,
184− .get_strings = mv88e6xxx_get_strings,
185− .get_ethtool_stats = mv88e6xxx_get_ethtool_stats,
186− .get_sset_count = mv88e6xxx_get_sset_count,
187− .adjust_link = mv88e6xxx_adjust_link,
188− .port_bridge_join = mv88e6xxx_port_bridge_join,
189− .port_bridge_leave = mv88e6xxx_port_bridge_leave,
190− .port_vlan_filtering = mv88e6xxx_port_vlan_filtering,
191− .port_vlan_prepare = mv88e6xxx_port_vlan_prepare,
192− .port_vlan_add = mv88e6xxx_port_vlan_add,
193− .port_vlan_del = mv88e6xxx_port_vlan_del,
194− .port_vlan_dump = mv88e6xxx_port_vlan_dump,
195− .port_fdb_prepare = mv88e6xxx_port_fdb_prepare,
196− .port_fdb_add = mv88e6xxx_port_fdb_add,
197− .port_fdb_del = mv88e6xxx_port_fdb_del,
198− .port_fdb_dump = mv88e6xxx_port_fdb_dump,
199−};
200−
201−MODULE_ALIAS("platform:mv88e6085");
202−MODULE_ALIAS("platform:mv88e6095");
203−MODULE_ALIAS("platform:mv88e6095f");
204−MODULE_ALIAS("platform:mv88e6131");
drivers/net/dsa/mv88e6171.c+0−151
@@ -1,151 +0,0 @@
1−/* net/dsa/mv88e6171.c - Marvell 88e6171 switch chip support
2− * Copyright (c) 2008-2009 Marvell Semiconductor
3− * Copyright (c) 2014 Claudio Leite <leitec@staticky.com>
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−
20−static const struct mv88e6xxx_info mv88e6171_table[] = {
21− {
22− .prod_num = PORT_SWITCH_ID_PROD_NUM_6171,
23− .family = MV88E6XXX_FAMILY_6351,
24− .name = "Marvell 88E6171",
25− .num_databases = 4096,
26− .num_ports = 7,
27− }, {
28− .prod_num = PORT_SWITCH_ID_PROD_NUM_6175,
29− .family = MV88E6XXX_FAMILY_6351,
30− .name = "Marvell 88E6175",
31− .num_databases = 4096,
32− .num_ports = 7,
33− }, {
34− .prod_num = PORT_SWITCH_ID_PROD_NUM_6350,
35− .family = MV88E6XXX_FAMILY_6351,
36− .name = "Marvell 88E6350",
37− .num_databases = 4096,
38− .num_ports = 7,
39− }, {
40− .prod_num = PORT_SWITCH_ID_PROD_NUM_6351,
41− .family = MV88E6XXX_FAMILY_6351,
42− .name = "Marvell 88E6351",
43− .num_databases = 4096,
44− .num_ports = 7,
45− }
46−};
47−
48−static const char *mv88e6171_drv_probe(struct device *dsa_dev,
49− struct device *host_dev, int sw_addr,
50− void **priv)
51−{
52− return mv88e6xxx_drv_probe(dsa_dev, host_dev, sw_addr, priv,
53− mv88e6171_table,
54− ARRAY_SIZE(mv88e6171_table));
55−}
56−
57−static int mv88e6171_setup_global(struct dsa_switch *ds)
58−{
59− struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
60− u32 upstream_port = dsa_upstream_port(ds);
61− int ret;
62− u32 reg;
63−
64− ret = mv88e6xxx_setup_global(ds);
65− if (ret)
66− return ret;
67−
68− /* Discard packets with excessive collisions, mask all
69− * interrupt sources, enable PPU.
70− */
71− ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL,
72− GLOBAL_CONTROL_PPU_ENABLE |
73− GLOBAL_CONTROL_DISCARD_EXCESS);
74− if (ret)
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 = upstream_port << GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT |
82− upstream_port << GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT |
83− upstream_port << GLOBAL_MONITOR_CONTROL_ARP_SHIFT |
84− upstream_port << GLOBAL_MONITOR_CONTROL_MIRROR_SHIFT;
85− ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_MONITOR_CONTROL, reg);
86− if (ret)
87− return ret;
88−
89− /* Disable remote management for now, and set the switch's
90− * DSA device number.
91− */
92− return mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL_2,
93− ds->index & 0x1f);
94−}
95−
96−static int mv88e6171_setup(struct dsa_switch *ds)
97−{
98− struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
99− int ret;
100−
101− ps->ds = ds;
102−
103− ret = mv88e6xxx_setup_common(ps);
104− if (ret < 0)
105− return ret;
106−
107− ret = mv88e6xxx_switch_reset(ps, true);
108− if (ret < 0)
109− return ret;
110−
111− ret = mv88e6171_setup_global(ds);
112− if (ret < 0)
113− return ret;
114−
115− return mv88e6xxx_setup_ports(ds);
116−}
117−
118−struct dsa_switch_driver mv88e6171_switch_driver = {
119− .tag_protocol = DSA_TAG_PROTO_EDSA,
120− .probe = mv88e6171_drv_probe,
121− .setup = mv88e6171_setup,
122− .set_addr = mv88e6xxx_set_addr_indirect,
123− .phy_read = mv88e6xxx_phy_read_indirect,
124− .phy_write = mv88e6xxx_phy_write_indirect,
125− .get_strings = mv88e6xxx_get_strings,
126− .get_ethtool_stats = mv88e6xxx_get_ethtool_stats,
127− .get_sset_count = mv88e6xxx_get_sset_count,
128− .adjust_link = mv88e6xxx_adjust_link,
129−#ifdef CONFIG_NET_DSA_HWMON
130− .get_temp = mv88e6xxx_get_temp,
131−#endif
132− .get_regs_len = mv88e6xxx_get_regs_len,
133− .get_regs = mv88e6xxx_get_regs,
134− .port_bridge_join = mv88e6xxx_port_bridge_join,
135− .port_bridge_leave = mv88e6xxx_port_bridge_leave,
136− .port_stp_state_set = mv88e6xxx_port_stp_state_set,
137− .port_vlan_filtering = mv88e6xxx_port_vlan_filtering,
138− .port_vlan_prepare = mv88e6xxx_port_vlan_prepare,
139− .port_vlan_add = mv88e6xxx_port_vlan_add,
140− .port_vlan_del = mv88e6xxx_port_vlan_del,
141− .port_vlan_dump = mv88e6xxx_port_vlan_dump,
142− .port_fdb_prepare = mv88e6xxx_port_fdb_prepare,
143− .port_fdb_add = mv88e6xxx_port_fdb_add,
144− .port_fdb_del = mv88e6xxx_port_fdb_del,
145− .port_fdb_dump = mv88e6xxx_port_fdb_dump,
146−};
147−
148−MODULE_ALIAS("platform:mv88e6171");
149−MODULE_ALIAS("platform:mv88e6175");
150−MODULE_ALIAS("platform:mv88e6350");
151−MODULE_ALIAS("platform:mv88e6351");
drivers/net/dsa/mv88e6352.c+0−377
@@ -1,377 +0,0 @@
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−
25−static const struct mv88e6xxx_info mv88e6352_table[] = {
26− {
27− .prod_num = PORT_SWITCH_ID_PROD_NUM_6320,
28− .family = MV88E6XXX_FAMILY_6320,
29− .name = "Marvell 88E6320",
30− .num_databases = 4096,
31− .num_ports = 7,
32− }, {
33− .prod_num = PORT_SWITCH_ID_PROD_NUM_6321,
34− .family = MV88E6XXX_FAMILY_6320,
35− .name = "Marvell 88E6321",
36− .num_databases = 4096,
37− .num_ports = 7,
38− }, {
39− .prod_num = PORT_SWITCH_ID_PROD_NUM_6172,
40− .family = MV88E6XXX_FAMILY_6352,
41− .name = "Marvell 88E6172",
42− .num_databases = 4096,
43− .num_ports = 7,
44− }, {
45− .prod_num = PORT_SWITCH_ID_PROD_NUM_6176,
46− .family = MV88E6XXX_FAMILY_6352,
47− .name = "Marvell 88E6176",
48− .num_databases = 4096,
49− .num_ports = 7,
50− }, {
51− .prod_num = PORT_SWITCH_ID_PROD_NUM_6240,
52− .family = MV88E6XXX_FAMILY_6352,
53− .name = "Marvell 88E6240",
54− .num_databases = 4096,
55− .num_ports = 7,
56− }, {
57− .prod_num = PORT_SWITCH_ID_PROD_NUM_6352,
58− .family = MV88E6XXX_FAMILY_6352,
59− .name = "Marvell 88E6352",
60− .num_databases = 4096,
61− .num_ports = 7,
62− }
63−};
64−
65−static const char *mv88e6352_drv_probe(struct device *dsa_dev,
66− struct device *host_dev, int sw_addr,
67− void **priv)
68−{
69− return mv88e6xxx_drv_probe(dsa_dev, host_dev, sw_addr, priv,
70− mv88e6352_table,
71− ARRAY_SIZE(mv88e6352_table));
72−}
73−
74−static int mv88e6352_setup_global(struct dsa_switch *ds)
75−{
76− struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
77− u32 upstream_port = dsa_upstream_port(ds);
78− int ret;
79− u32 reg;
80−
81− ret = mv88e6xxx_setup_global(ds);
82− if (ret)
83− return ret;
84−
85− /* Discard packets with excessive collisions,
86− * mask all interrupt sources, enable PPU (bit 14, undocumented).
87− */
88− ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL,
89− GLOBAL_CONTROL_PPU_ENABLE |
90− GLOBAL_CONTROL_DISCARD_EXCESS);
91− if (ret)
92− return ret;
93−
94− /* Configure the upstream port, and configure the upstream
95− * port as the port to which ingress and egress monitor frames
96− * are to be sent.
97− */
98− reg = upstream_port << GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT |
99− upstream_port << GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT |
100− upstream_port << GLOBAL_MONITOR_CONTROL_ARP_SHIFT;
101− ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_MONITOR_CONTROL, reg);
102− if (ret)
103− return ret;
104−
105− /* Disable remote management for now, and set the switch's
106− * DSA device number.
107− */
108− return mv88e6xxx_reg_write(ps, REG_GLOBAL, 0x1c, ds->index & 0x1f);
109−}
110−
111−static int mv88e6352_setup(struct dsa_switch *ds)
112−{
113− struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
114− int ret;
115−
116− ps->ds = ds;
117−
118− ret = mv88e6xxx_setup_common(ps);
119− if (ret < 0)
120− return ret;
121−
122− mutex_init(&ps->eeprom_mutex);
123−
124− ret = mv88e6xxx_switch_reset(ps, true);
125− if (ret < 0)
126− return ret;
127−
128− ret = mv88e6352_setup_global(ds);
129− if (ret < 0)
130− return ret;
131−
132− return mv88e6xxx_setup_ports(ds);
133−}
134−
135−static int mv88e6352_read_eeprom_word(struct dsa_switch *ds, int addr)
136−{
137− struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
138− int ret;
139−
140− mutex_lock(&ps->eeprom_mutex);
141−
142− ret = mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_EEPROM_OP,
143− GLOBAL2_EEPROM_OP_READ |
144− (addr & GLOBAL2_EEPROM_OP_ADDR_MASK));
145− if (ret < 0)
146− goto error;
147−
148− ret = mv88e6xxx_eeprom_busy_wait(ds);
149− if (ret < 0)
150− goto error;
151−
152− ret = mv88e6xxx_reg_read(ps, REG_GLOBAL2, GLOBAL2_EEPROM_DATA);
153−error:
154− mutex_unlock(&ps->eeprom_mutex);
155− return ret;
156−}
157−
158−static int mv88e6352_get_eeprom(struct dsa_switch *ds,
159− struct ethtool_eeprom *eeprom, u8 *data)
160−{
161− int offset;
162− int len;
163− int ret;
164−
165− offset = eeprom->offset;
166− len = eeprom->len;
167− eeprom->len = 0;
168−
169− eeprom->magic = 0xc3ec4951;
170−
171− ret = mv88e6xxx_eeprom_load_wait(ds);
172− if (ret < 0)
173− return ret;
174−
175− if (offset & 1) {
176− int word;
177−
178− word = mv88e6352_read_eeprom_word(ds, offset >> 1);
179− if (word < 0)
180− return word;
181−
182− *data++ = (word >> 8) & 0xff;
183−
184− offset++;
185− len--;
186− eeprom->len++;
187− }
188−
189− while (len >= 2) {
190− int word;
191−
192− word = mv88e6352_read_eeprom_word(ds, offset >> 1);
193− if (word < 0)
194− return word;
195−
196− *data++ = word & 0xff;
197− *data++ = (word >> 8) & 0xff;
198−
199− offset += 2;
200− len -= 2;
201− eeprom->len += 2;
202− }
203−
204− if (len) {
205− int word;
206−
207− word = mv88e6352_read_eeprom_word(ds, offset >> 1);
208− if (word < 0)
209− return word;
210−
211− *data++ = word & 0xff;
212−
213− offset++;
214− len--;
215− eeprom->len++;
216− }
217−
218− return 0;
219−}
220−
221−static int mv88e6352_eeprom_is_readonly(struct dsa_switch *ds)
222−{
223− struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
224− int ret;
225−
226− ret = mv88e6xxx_reg_read(ps, REG_GLOBAL2, GLOBAL2_EEPROM_OP);
227− if (ret < 0)
228− return ret;
229−
230− if (!(ret & GLOBAL2_EEPROM_OP_WRITE_EN))
231− return -EROFS;
232−
233− return 0;
234−}
235−
236−static int mv88e6352_write_eeprom_word(struct dsa_switch *ds, int addr,
237− u16 data)
238−{
239− struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
240− int ret;
241−
242− mutex_lock(&ps->eeprom_mutex);
243−
244− ret = mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_EEPROM_DATA, data);
245− if (ret < 0)
246− goto error;
247−
248− ret = mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_EEPROM_OP,
249− GLOBAL2_EEPROM_OP_WRITE |
250− (addr & GLOBAL2_EEPROM_OP_ADDR_MASK));
251− if (ret < 0)
252− goto error;
253−
254− ret = mv88e6xxx_eeprom_busy_wait(ds);
255−error:
256− mutex_unlock(&ps->eeprom_mutex);
257− return ret;
258−}
259−
260−static int mv88e6352_set_eeprom(struct dsa_switch *ds,
261− struct ethtool_eeprom *eeprom, u8 *data)
262−{
263− int offset;
264− int ret;
265− int len;
266−
267− if (eeprom->magic != 0xc3ec4951)
268− return -EINVAL;
269−
270− ret = mv88e6352_eeprom_is_readonly(ds);
271− if (ret)
272− return ret;
273−
274− offset = eeprom->offset;
275− len = eeprom->len;
276− eeprom->len = 0;
277−
278− ret = mv88e6xxx_eeprom_load_wait(ds);
279− if (ret < 0)
280− return ret;
281−
282− if (offset & 1) {
283− int word;
284−
285− word = mv88e6352_read_eeprom_word(ds, offset >> 1);
286− if (word < 0)
287− return word;
288−
289− word = (*data++ << 8) | (word & 0xff);
290−
291− ret = mv88e6352_write_eeprom_word(ds, offset >> 1, word);
292− if (ret < 0)
293− return ret;
294−
295− offset++;
296− len--;
297− eeprom->len++;
298− }
299−
300− while (len >= 2) {
301− int word;
302−
303− word = *data++;
304− word |= *data++ << 8;
305−
306− ret = mv88e6352_write_eeprom_word(ds, offset >> 1, word);
307− if (ret < 0)
308− return ret;
309−
310− offset += 2;
311− len -= 2;
312− eeprom->len += 2;
313− }
314−
315− if (len) {
316− int word;
317−
318− word = mv88e6352_read_eeprom_word(ds, offset >> 1);
319− if (word < 0)
320− return word;
321−
322− word = (word & 0xff00) | *data++;
323−
324− ret = mv88e6352_write_eeprom_word(ds, offset >> 1, word);
325− if (ret < 0)
326− return ret;
327−
328− offset++;
329− len--;
330− eeprom->len++;
331− }
332−
333− return 0;
334−}
335−
336−struct dsa_switch_driver mv88e6352_switch_driver = {
337− .tag_protocol = DSA_TAG_PROTO_EDSA,
338− .probe = mv88e6352_drv_probe,
339− .setup = mv88e6352_setup,
340− .set_addr = mv88e6xxx_set_addr_indirect,
341− .phy_read = mv88e6xxx_phy_read_indirect,
342− .phy_write = mv88e6xxx_phy_write_indirect,
343− .get_strings = mv88e6xxx_get_strings,
344− .get_ethtool_stats = mv88e6xxx_get_ethtool_stats,
345− .get_sset_count = mv88e6xxx_get_sset_count,
346− .adjust_link = mv88e6xxx_adjust_link,
347− .set_eee = mv88e6xxx_set_eee,
348− .get_eee = mv88e6xxx_get_eee,
349−#ifdef CONFIG_NET_DSA_HWMON
350− .get_temp = mv88e6xxx_get_temp,
351− .get_temp_limit = mv88e6xxx_get_temp_limit,
352− .set_temp_limit = mv88e6xxx_set_temp_limit,
353− .get_temp_alarm = mv88e6xxx_get_temp_alarm,
354−#endif
355− .get_eeprom = mv88e6352_get_eeprom,
356− .set_eeprom = mv88e6352_set_eeprom,
357− .get_regs_len = mv88e6xxx_get_regs_len,
358− .get_regs = mv88e6xxx_get_regs,
359− .port_bridge_join = mv88e6xxx_port_bridge_join,
360− .port_bridge_leave = mv88e6xxx_port_bridge_leave,
361− .port_stp_state_set = mv88e6xxx_port_stp_state_set,
362− .port_vlan_filtering = mv88e6xxx_port_vlan_filtering,
363− .port_vlan_prepare = mv88e6xxx_port_vlan_prepare,
364− .port_vlan_add = mv88e6xxx_port_vlan_add,
365− .port_vlan_del = mv88e6xxx_port_vlan_del,
366− .port_vlan_dump = mv88e6xxx_port_vlan_dump,
367− .port_fdb_prepare = mv88e6xxx_port_fdb_prepare,
368− .port_fdb_add = mv88e6xxx_port_fdb_add,
369− .port_fdb_del = mv88e6xxx_port_fdb_del,
370− .port_fdb_dump = mv88e6xxx_port_fdb_dump,
371−};
372−
373−MODULE_ALIAS("platform:mv88e6172");
374−MODULE_ALIAS("platform:mv88e6176");
375−MODULE_ALIAS("platform:mv88e6320");
376−MODULE_ALIAS("platform:mv88e6321");
377−MODULE_ALIAS("platform:mv88e6352");
drivers/net/dsa/mv88e6xxx.c+733−253
@@ -173,7 +173,7 @@ int mv88e6xxx_reg_write(struct mv88e6xxx_priv_state *ps, int addr, · 172 unmodified lines
173173 return ret;
174174 }
175175
176−int mv88e6xxx_set_addr_direct(struct dsa_switch *ds, u8 *addr)
176+static int mv88e6xxx_set_addr_direct(struct dsa_switch *ds, u8 *addr)
177177 {
178178 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
179179 int err;
@@ -192,7 +192,7 @@ int mv88e6xxx_set_addr_direct(struct dsa_switch *ds, u8 *addr) · 12 unmodified lines
192192 (addr[4] << 8) | addr[5]);
193193 }
194194
195−int mv88e6xxx_set_addr_indirect(struct dsa_switch *ds, u8 *addr)
195+static int mv88e6xxx_set_addr_indirect(struct dsa_switch *ds, u8 *addr)
196196 {
197197 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
198198 int ret;
@@ -225,6 +225,16 @@ int mv88e6xxx_set_addr_indirect(struct dsa_switch *ds, u8 *addr) · 26 unmodified lines
225225 return 0;
226226 }
227227
228+int mv88e6xxx_set_addr(struct dsa_switch *ds, u8 *addr)
229+{
230+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
231+
232+ if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_SWITCH_MAC))
233+ return mv88e6xxx_set_addr_indirect(ds, addr);
234+ else
235+ return mv88e6xxx_set_addr_direct(ds, addr);
236+}
237+
228238 static int _mv88e6xxx_phy_read(struct mv88e6xxx_priv_state *ps, int addr,
229239 int regnum)
230240 {
@@ -241,24 +251,23 @@ static int _mv88e6xxx_phy_write(struct mv88e6xxx_priv_state *ps, int addr, · 10 unmodified lines
241251 return 0;
242252 }
243253
244−#ifdef CONFIG_NET_DSA_MV88E6XXX_NEED_PPU
245254 static int mv88e6xxx_ppu_disable(struct mv88e6xxx_priv_state *ps)
246255 {
247256 int ret;
248257 unsigned long timeout;
249258
250− ret = mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_CONTROL);
259+ ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_CONTROL);
251260 if (ret < 0)
252261 return ret;
253262
254− ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL,
255− ret & ~GLOBAL_CONTROL_PPU_ENABLE);
263+ ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL,
264+ ret & ~GLOBAL_CONTROL_PPU_ENABLE);
256265 if (ret)
257266 return ret;
258267
259268 timeout = jiffies + 1 * HZ;
260269 while (time_before(jiffies, timeout)) {
261− ret = mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_STATUS);
270+ ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_STATUS);
262271 if (ret < 0)
263272 return ret;
264273
@@ -361,35 +370,33 @@ void mv88e6xxx_ppu_state_init(struct mv88e6xxx_priv_state *ps) · 96 unmodified lines
361370 ps->ppu_timer.function = mv88e6xxx_ppu_reenable_timer;
362371 }
363372
364−int mv88e6xxx_phy_read_ppu(struct dsa_switch *ds, int addr, int regnum)
373+static int mv88e6xxx_phy_read_ppu(struct mv88e6xxx_priv_state *ps, int addr,
374+ int regnum)
365375 {
366− struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
367376 int ret;
368377
369378 ret = mv88e6xxx_ppu_access_get(ps);
370379 if (ret >= 0) {
371− ret = mv88e6xxx_reg_read(ps, addr, regnum);
380+ ret = _mv88e6xxx_reg_read(ps, addr, regnum);
372381 mv88e6xxx_ppu_access_put(ps);
373382 }
374383
375384 return ret;
376385 }
377386
378−int mv88e6xxx_phy_write_ppu(struct dsa_switch *ds, int addr,
379− int regnum, u16 val)
387+static int mv88e6xxx_phy_write_ppu(struct mv88e6xxx_priv_state *ps, int addr,
388+ int regnum, u16 val)
380389 {
381− struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
382390 int ret;
383391
384392 ret = mv88e6xxx_ppu_access_get(ps);
385393 if (ret >= 0) {
386− ret = mv88e6xxx_reg_write(ps, addr, regnum, val);
394+ ret = _mv88e6xxx_reg_write(ps, addr, regnum, val);
387395 mv88e6xxx_ppu_access_put(ps);
388396 }
389397
390398 return ret;
391399 }
392−#endif
393400
394401 static bool mv88e6xxx_6065_family(struct mv88e6xxx_priv_state *ps)
395402 {
@@ -460,8 +467,8 @@ static bool mv88e6xxx_has_stu(struct mv88e6xxx_priv_state *ps) · 64 unmodified lines
460467 * phy. However, in the case of a fixed link phy, we force the port
461468 * settings from the fixed link settings.
462469 */
463−void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port,
464− struct phy_device *phydev)
470+static void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port,
471+ struct phy_device *phydev)
465472 {
466473 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
467474 u32 reg;
@@ -707,7 +714,8 @@ static uint64_t _mv88e6xxx_get_ethtool_stat(struct mv88e6xxx_priv_state *ps, · 239 unmodified lines
707714 return value;
708715 }
709716
710−void mv88e6xxx_get_strings(struct dsa_switch *ds, int port, uint8_t *data)
717+static void mv88e6xxx_get_strings(struct dsa_switch *ds, int port,
718+ uint8_t *data)
711719 {
712720 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
713721 struct mv88e6xxx_hw_stat *stat;
@@ -723,7 +731,7 @@ void mv88e6xxx_get_strings(struct dsa_switch *ds, int port, uint8_t *data) · 9 unmodified lines
723731 }
724732 }
725733
726−int mv88e6xxx_get_sset_count(struct dsa_switch *ds)
734+static int mv88e6xxx_get_sset_count(struct dsa_switch *ds)
727735 {
728736 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
729737 struct mv88e6xxx_hw_stat *stat;
@@ -737,9 +745,8 @@ int mv88e6xxx_get_sset_count(struct dsa_switch *ds) · 7 unmodified lines
737745 return j;
738746 }
739747
740−void
741−mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds,
742− int port, uint64_t *data)
748+static void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, int port,
749+ uint64_t *data)
743750 {
744751 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
745752 struct mv88e6xxx_hw_stat *stat;
@@ -764,13 +771,13 @@ mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, · 18 unmodified lines
764771 mutex_unlock(&ps->smi_mutex);
765772 }
766773
767−int mv88e6xxx_get_regs_len(struct dsa_switch *ds, int port)
774+static int mv88e6xxx_get_regs_len(struct dsa_switch *ds, int port)
768775 {
769776 return 32 * sizeof(u16);
770777 }
771778
772−void mv88e6xxx_get_regs(struct dsa_switch *ds, int port,
773− struct ethtool_regs *regs, void *_p)
779+static void mv88e6xxx_get_regs(struct dsa_switch *ds, int port,
780+ struct ethtool_regs *regs, void *_p)
774781 {
775782 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
776783 u16 *p = _p;
@@ -780,13 +787,17 @@ void mv88e6xxx_get_regs(struct dsa_switch *ds, int port, · 3 unmodified lines
780787
781788 memset(p, 0xff, 32 * sizeof(u16));
782789
790+ mutex_lock(&ps->smi_mutex);
791+
783792 for (i = 0; i < 32; i++) {
784793 int ret;
785794
786− ret = mv88e6xxx_reg_read(ps, REG_PORT(port), i);
795+ ret = _mv88e6xxx_reg_read(ps, REG_PORT(port), i);
787796 if (ret >= 0)
788797 p[i] = ret;
789798 }
799+
800+ mutex_unlock(&ps->smi_mutex);
790801 }
791802
792803 static int _mv88e6xxx_wait(struct mv88e6xxx_priv_state *ps, int reg, int offset,
@@ -826,7 +837,7 @@ static int _mv88e6xxx_phy_wait(struct mv88e6xxx_priv_state *ps) · 33 unmodified lines
826837 GLOBAL2_SMI_OP_BUSY);
827838 }
828839
829−int mv88e6xxx_eeprom_load_wait(struct dsa_switch *ds)
840+static int mv88e6xxx_eeprom_load_wait(struct dsa_switch *ds)
830841 {
831842 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
832843
@@ -834,7 +845,7 @@ int mv88e6xxx_eeprom_load_wait(struct dsa_switch *ds) · 1 unmodified line
834845 GLOBAL2_EEPROM_OP_LOAD);
835846 }
836847
837−int mv88e6xxx_eeprom_busy_wait(struct dsa_switch *ds)
848+static int mv88e6xxx_eeprom_busy_wait(struct dsa_switch *ds)
838849 {
839850 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
840851
@@ -842,6 +853,215 @@ int mv88e6xxx_eeprom_busy_wait(struct dsa_switch *ds) · 1 unmodified line
842853 GLOBAL2_EEPROM_OP_BUSY);
843854 }
844855
856+static int mv88e6xxx_read_eeprom_word(struct dsa_switch *ds, int addr)
857+{
858+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
859+ int ret;
860+
861+ mutex_lock(&ps->eeprom_mutex);
862+
863+ ret = mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_EEPROM_OP,
864+ GLOBAL2_EEPROM_OP_READ |
865+ (addr & GLOBAL2_EEPROM_OP_ADDR_MASK));
866+ if (ret < 0)
867+ goto error;
868+
869+ ret = mv88e6xxx_eeprom_busy_wait(ds);
870+ if (ret < 0)
871+ goto error;
872+
873+ ret = mv88e6xxx_reg_read(ps, REG_GLOBAL2, GLOBAL2_EEPROM_DATA);
874+error:
875+ mutex_unlock(&ps->eeprom_mutex);
876+ return ret;
877+}
878+
879+static int mv88e6xxx_get_eeprom(struct dsa_switch *ds,
880+ struct ethtool_eeprom *eeprom, u8 *data)
881+{
882+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
883+ int offset;
884+ int len;
885+ int ret;
886+
887+ if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_EEPROM))
888+ return -EOPNOTSUPP;
889+
890+ offset = eeprom->offset;
891+ len = eeprom->len;
892+ eeprom->len = 0;
893+
894+ eeprom->magic = 0xc3ec4951;
895+
896+ ret = mv88e6xxx_eeprom_load_wait(ds);
897+ if (ret < 0)
898+ return ret;
899+
900+ if (offset & 1) {
901+ int word;
902+
903+ word = mv88e6xxx_read_eeprom_word(ds, offset >> 1);
904+ if (word < 0)
905+ return word;
906+
907+ *data++ = (word >> 8) & 0xff;
908+
909+ offset++;
910+ len--;
911+ eeprom->len++;
912+ }
913+
914+ while (len >= 2) {
915+ int word;
916+
917+ word = mv88e6xxx_read_eeprom_word(ds, offset >> 1);
918+ if (word < 0)
919+ return word;
920+
921+ *data++ = word & 0xff;
922+ *data++ = (word >> 8) & 0xff;
923+
924+ offset += 2;
925+ len -= 2;
926+ eeprom->len += 2;
927+ }
928+
929+ if (len) {
930+ int word;
931+
932+ word = mv88e6xxx_read_eeprom_word(ds, offset >> 1);
933+ if (word < 0)
934+ return word;
935+
936+ *data++ = word & 0xff;
937+
938+ offset++;
939+ len--;
940+ eeprom->len++;
941+ }
942+
943+ return 0;
944+}
945+
946+static int mv88e6xxx_eeprom_is_readonly(struct dsa_switch *ds)
947+{
948+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
949+ int ret;
950+
951+ ret = mv88e6xxx_reg_read(ps, REG_GLOBAL2, GLOBAL2_EEPROM_OP);
952+ if (ret < 0)
953+ return ret;
954+
955+ if (!(ret & GLOBAL2_EEPROM_OP_WRITE_EN))
956+ return -EROFS;
957+
958+ return 0;
959+}
960+
961+static int mv88e6xxx_write_eeprom_word(struct dsa_switch *ds, int addr,
962+ u16 data)
963+{
964+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
965+ int ret;
966+
967+ mutex_lock(&ps->eeprom_mutex);
968+
969+ ret = mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_EEPROM_DATA, data);
970+ if (ret < 0)
971+ goto error;
972+
973+ ret = mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_EEPROM_OP,
974+ GLOBAL2_EEPROM_OP_WRITE |
975+ (addr & GLOBAL2_EEPROM_OP_ADDR_MASK));
976+ if (ret < 0)
977+ goto error;
978+
979+ ret = mv88e6xxx_eeprom_busy_wait(ds);
980+error:
981+ mutex_unlock(&ps->eeprom_mutex);
982+ return ret;
983+}
984+
985+static int mv88e6xxx_set_eeprom(struct dsa_switch *ds,
986+ struct ethtool_eeprom *eeprom, u8 *data)
987+{
988+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
989+ int offset;
990+ int ret;
991+ int len;
992+
993+ if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_EEPROM))
994+ return -EOPNOTSUPP;
995+
996+ if (eeprom->magic != 0xc3ec4951)
997+ return -EINVAL;
998+
999+ ret = mv88e6xxx_eeprom_is_readonly(ds);
1000+ if (ret)
1001+ return ret;
1002+
1003+ offset = eeprom->offset;
1004+ len = eeprom->len;
1005+ eeprom->len = 0;
1006+
1007+ ret = mv88e6xxx_eeprom_load_wait(ds);
1008+ if (ret < 0)
1009+ return ret;
1010+
1011+ if (offset & 1) {
1012+ int word;
1013+
1014+ word = mv88e6xxx_read_eeprom_word(ds, offset >> 1);
1015+ if (word < 0)
1016+ return word;
1017+
1018+ word = (*data++ << 8) | (word & 0xff);
1019+
1020+ ret = mv88e6xxx_write_eeprom_word(ds, offset >> 1, word);
1021+ if (ret < 0)
1022+ return ret;
1023+
1024+ offset++;
1025+ len--;
1026+ eeprom->len++;
1027+ }
1028+
1029+ while (len >= 2) {
1030+ int word;
1031+
1032+ word = *data++;
1033+ word |= *data++ << 8;
1034+
1035+ ret = mv88e6xxx_write_eeprom_word(ds, offset >> 1, word);
1036+ if (ret < 0)
1037+ return ret;
1038+
1039+ offset += 2;
1040+ len -= 2;
1041+ eeprom->len += 2;
1042+ }
1043+
1044+ if (len) {
1045+ int word;
1046+
1047+ word = mv88e6xxx_read_eeprom_word(ds, offset >> 1);
1048+ if (word < 0)
1049+ return word;
1050+
1051+ word = (word & 0xff00) | *data++;
1052+
1053+ ret = mv88e6xxx_write_eeprom_word(ds, offset >> 1, word);
1054+ if (ret < 0)
1055+ return ret;
1056+
1057+ offset++;
1058+ len--;
1059+ eeprom->len++;
1060+ }
1061+
1062+ return 0;
1063+}
1064+
8451065 static int _mv88e6xxx_atu_wait(struct mv88e6xxx_priv_state *ps)
8461066 {
8471067 return _mv88e6xxx_wait(ps, REG_GLOBAL, GLOBAL_ATU_OP,
@@ -884,11 +1104,15 @@ static int _mv88e6xxx_phy_write_indirect(struct mv88e6xxx_priv_state *ps, · 36 unmodified lines
8841104 return _mv88e6xxx_phy_wait(ps);
8851105 }
8861106
887−int mv88e6xxx_get_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e)
1107+static int mv88e6xxx_get_eee(struct dsa_switch *ds, int port,
1108+ struct ethtool_eee *e)
8881109 {
8891110 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
8901111 int reg;
8911112
1113+ if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_EEE))
1114+ return -EOPNOTSUPP;
1115+
8921116 mutex_lock(&ps->smi_mutex);
8931117
8941118 reg = _mv88e6xxx_phy_read_indirect(ps, port, 16);
@@ -910,13 +1134,16 @@ out: · 15 unmodified lines
9101134 return reg;
9111135 }
9121136
913−int mv88e6xxx_set_eee(struct dsa_switch *ds, int port,
914− struct phy_device *phydev, struct ethtool_eee *e)
1137+static int mv88e6xxx_set_eee(struct dsa_switch *ds, int port,
1138+ struct phy_device *phydev, struct ethtool_eee *e)
9151139 {
9161140 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
9171141 int reg;
9181142 int ret;
9191143
1144+ if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_EEE))
1145+ return -EOPNOTSUPP;
1146+
9201147 mutex_lock(&ps->smi_mutex);
9211148
9221149 ret = _mv88e6xxx_phy_read_indirect(ps, port, 16);
@@ -1138,11 +1365,15 @@ static int _mv88e6xxx_port_based_vlan_map(struct mv88e6xxx_priv_state *ps, · 215 unmodified lines
11381365 return _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_BASE_VLAN, reg);
11391366 }
11401367
1141−void mv88e6xxx_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
1368+static void mv88e6xxx_port_stp_state_set(struct dsa_switch *ds, int port,
1369+ u8 state)
11421370 {
11431371 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
11441372 int stp_state;
11451373
1374+ if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_PORTSTATE))
1375+ return;
1376+
11461377 switch (state) {
11471378 case BR_STATE_DISABLED:
11481379 stp_state = PORT_CONTROL_STATE_DISABLED;
@@ -1358,15 +1589,18 @@ static int _mv88e6xxx_vtu_getnext(struct mv88e6xxx_priv_state *ps, · 209 unmodified lines
13581589 return 0;
13591590 }
13601591
1361−int mv88e6xxx_port_vlan_dump(struct dsa_switch *ds, int port,
1362− struct switchdev_obj_port_vlan *vlan,
1363− int (*cb)(struct switchdev_obj *obj))
1592+static int mv88e6xxx_port_vlan_dump(struct dsa_switch *ds, int port,
1593+ struct switchdev_obj_port_vlan *vlan,
1594+ int (*cb)(struct switchdev_obj *obj))
13641595 {
13651596 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
13661597 struct mv88e6xxx_vtu_stu_entry next;
13671598 u16 pvid;
13681599 int err;
13691600
1601+ if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_VTU))
1602+ return -EOPNOTSUPP;
1603+
13701604 mutex_lock(&ps->smi_mutex);
13711605
13721606 err = _mv88e6xxx_port_pvid_get(ps, port, &pvid);
@@ -1782,14 +2016,17 @@ static const char * const mv88e6xxx_port_8021q_mode_names[] = { · 409 unmodified lines
17822016 [PORT_CONTROL_2_8021Q_SECURE] = "Secure",
17832017 };
17842018
1785−int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port,
1786− bool vlan_filtering)
2019+static int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port,
2020+ bool vlan_filtering)
17872021 {
17882022 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
17892023 u16 old, new = vlan_filtering ? PORT_CONTROL_2_8021Q_SECURE :
17902024 PORT_CONTROL_2_8021Q_DISABLED;
17912025 int ret;
17922026
2027+ if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_VTU))
2028+ return -EOPNOTSUPP;
2029+
17932030 mutex_lock(&ps->smi_mutex);
17942031
17952032 ret = _mv88e6xxx_reg_read(ps, REG_PORT(port), PORT_CONTROL_2);
@@ -1819,12 +2056,16 @@ unlock: · 23 unmodified lines
18192056 return ret;
18202057 }
18212058
1822−int mv88e6xxx_port_vlan_prepare(struct dsa_switch *ds, int port,
1823− const struct switchdev_obj_port_vlan *vlan,
1824− struct switchdev_trans *trans)
2059+static int mv88e6xxx_port_vlan_prepare(struct dsa_switch *ds, int port,
2060+ const struct switchdev_obj_port_vlan *vlan,
2061+ struct switchdev_trans *trans)
18252062 {
2063+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
18262064 int err;
18272065
2066+ if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_VTU))
2067+ return -EOPNOTSUPP;
2068+
18282069 /* If the requested port doesn't belong to the same bridge as the VLAN
18292070 * members, do not support it (yet) and fallback to software VLAN.
18302071 */
@@ -1856,15 +2097,18 @@ static int _mv88e6xxx_port_vlan_add(struct mv88e6xxx_priv_state *ps, int port, · 25 unmodified lines
18562097 return _mv88e6xxx_vtu_loadpurge(ps, &vlan);
18572098 }
18582099
1859−void mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port,
1860− const struct switchdev_obj_port_vlan *vlan,
1861− struct switchdev_trans *trans)
2100+static void mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port,
2101+ const struct switchdev_obj_port_vlan *vlan,
2102+ struct switchdev_trans *trans)
18622103 {
18632104 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
18642105 bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
18652106 bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
18662107 u16 vid;
18672108
2109+ if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_VTU))
2110+ return;
2111+
18682112 mutex_lock(&ps->smi_mutex);
18692113
18702114 for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid)
@@ -1915,13 +2159,16 @@ static int _mv88e6xxx_port_vlan_del(struct mv88e6xxx_priv_state *ps, · 44 unmodified lines
19152159 return _mv88e6xxx_atu_remove(ps, vlan.fid, port, false);
19162160 }
19172161
1918−int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port,
1919− const struct switchdev_obj_port_vlan *vlan)
2162+static int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port,
2163+ const struct switchdev_obj_port_vlan *vlan)
19202164 {
19212165 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
19222166 u16 pvid, vid;
19232167 int err = 0;
19242168
2169+ if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_VTU))
2170+ return -EOPNOTSUPP;
2171+
19252172 mutex_lock(&ps->smi_mutex);
19262173
19272174 err = _mv88e6xxx_port_pvid_get(ps, port, &pvid);
@@ -2026,37 +2273,48 @@ static int _mv88e6xxx_port_fdb_load(struct mv88e6xxx_priv_state *ps, int port, · 98 unmodified lines
20262273 return _mv88e6xxx_atu_load(ps, &entry);
20272274 }
20282275
2029−int mv88e6xxx_port_fdb_prepare(struct dsa_switch *ds, int port,
2030− const struct switchdev_obj_port_fdb *fdb,
2031− struct switchdev_trans *trans)
2276+static int mv88e6xxx_port_fdb_prepare(struct dsa_switch *ds, int port,
2277+ const struct switchdev_obj_port_fdb *fdb,
2278+ struct switchdev_trans *trans)
20322279 {
2280+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
2281+
2282+ if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_ATU))
2283+ return -EOPNOTSUPP;
2284+
20332285 /* We don't need any dynamic resource from the kernel (yet),
20342286 * so skip the prepare phase.
20352287 */
20362288 return 0;
20372289 }
20382290
2039−void mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port,
2040− const struct switchdev_obj_port_fdb *fdb,
2041− struct switchdev_trans *trans)
2291+static void mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port,
2292+ const struct switchdev_obj_port_fdb *fdb,
2293+ struct switchdev_trans *trans)
20422294 {
20432295 int state = is_multicast_ether_addr(fdb->addr) ?
20442296 GLOBAL_ATU_DATA_STATE_MC_STATIC :
20452297 GLOBAL_ATU_DATA_STATE_UC_STATIC;
20462298 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
20472299
2300+ if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_ATU))
2301+ return;
2302+
20482303 mutex_lock(&ps->smi_mutex);
20492304 if (_mv88e6xxx_port_fdb_load(ps, port, fdb->addr, fdb->vid, state))
20502305 netdev_err(ds->ports[port], "failed to load MAC address\n");
20512306 mutex_unlock(&ps->smi_mutex);
20522307 }
20532308
2054−int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port,
2055− const struct switchdev_obj_port_fdb *fdb)
2309+static int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port,
2310+ const struct switchdev_obj_port_fdb *fdb)
20562311 {
20572312 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
20582313 int ret;
20592314
2315+ if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_ATU))
2316+ return -EOPNOTSUPP;
2317+
20602318 mutex_lock(&ps->smi_mutex);
20612319 ret = _mv88e6xxx_port_fdb_load(ps, port, fdb->addr, fdb->vid,
20622320 GLOBAL_ATU_DATA_STATE_UNUSED);
@@ -2151,9 +2409,9 @@ static int _mv88e6xxx_port_fdb_dump_one(struct mv88e6xxx_priv_state *ps, · 88 unmodified lines
21512409 return err;
21522410 }
21532411
2154−int mv88e6xxx_port_fdb_dump(struct dsa_switch *ds, int port,
2155− struct switchdev_obj_port_fdb *fdb,
2156− int (*cb)(struct switchdev_obj *obj))
2412+static int mv88e6xxx_port_fdb_dump(struct dsa_switch *ds, int port,
2413+ struct switchdev_obj_port_fdb *fdb,
2414+ int (*cb)(struct switchdev_obj *obj))
21572415 {
21582416 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
21592417 struct mv88e6xxx_vtu_stu_entry vlan = {
@@ -2162,6 +2420,9 @@ int mv88e6xxx_port_fdb_dump(struct dsa_switch *ds, int port, · 2 unmodified lines
21622420 u16 fid;
21632421 int err;
21642422
2423+ if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_ATU))
2424+ return -EOPNOTSUPP;
2425+
21652426 mutex_lock(&ps->smi_mutex);
21662427
21672428 /* Dump port's default Filtering Information Database (VLAN ID 0) */
@@ -2198,12 +2459,15 @@ unlock: · 30 unmodified lines
21982459 return err;
21992460 }
22002461
2201−int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port,
2202− struct net_device *bridge)
2462+static int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port,
2463+ struct net_device *bridge)
22032464 {
22042465 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
22052466 int i, err = 0;
22062467
2468+ if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_VLANTABLE))
2469+ return -EOPNOTSUPP;
2470+
22072471 mutex_lock(&ps->smi_mutex);
22082472
22092473 /* Assign the bridge and remap each port's VLANTable */
@@ -2222,12 +2486,15 @@ int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port, · 12 unmodified lines
22222486 return err;
22232487 }
22242488
2225−void mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port)
2489+static void mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port)
22262490 {
22272491 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
22282492 struct net_device *bridge = ps->ports[port].bridge_dev;
22292493 int i;
22302494
2495+ if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_VLANTABLE))
2496+ return;
2497+
22312498 mutex_lock(&ps->smi_mutex);
22322499
22332500 /* Unassign the bridge and remap each port's VLANTable */
@@ -2294,6 +2561,68 @@ restore_page_0: · 60 unmodified lines
22942561 return ret;
22952562 }
22962563
2564+static int mv88e6xxx_switch_reset(struct mv88e6xxx_priv_state *ps)
2565+{
2566+ bool ppu_active = mv88e6xxx_has(ps, MV88E6XXX_FLAG_PPU_ACTIVE);
2567+ u16 is_reset = (ppu_active ? 0x8800 : 0xc800);
2568+ struct gpio_desc *gpiod = ps->ds->pd->reset;
2569+ unsigned long timeout;
2570+ int ret;
2571+ int i;
2572+
2573+ /* Set all ports to the disabled state. */
2574+ for (i = 0; i < ps->info->num_ports; i++) {
2575+ ret = _mv88e6xxx_reg_read(ps, REG_PORT(i), PORT_CONTROL);
2576+ if (ret < 0)
2577+ return ret;
2578+
2579+ ret = _mv88e6xxx_reg_write(ps, REG_PORT(i), PORT_CONTROL,
2580+ ret & 0xfffc);
2581+ if (ret)
2582+ return ret;
2583+ }
2584+
2585+ /* Wait for transmit queues to drain. */
2586+ usleep_range(2000, 4000);
2587+
2588+ /* If there is a gpio connected to the reset pin, toggle it */
2589+ if (gpiod) {
2590+ gpiod_set_value_cansleep(gpiod, 1);
2591+ usleep_range(10000, 20000);
2592+ gpiod_set_value_cansleep(gpiod, 0);
2593+ usleep_range(10000, 20000);
2594+ }
2595+
2596+ /* Reset the switch. Keep the PPU active if requested. The PPU
2597+ * needs to be active to support indirect phy register access
2598+ * through global registers 0x18 and 0x19.
2599+ */
2600+ if (ppu_active)
2601+ ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, 0x04, 0xc000);
2602+ else
2603+ ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, 0x04, 0xc400);
2604+ if (ret)
2605+ return ret;
2606+
2607+ /* Wait up to one second for reset to complete. */
2608+ timeout = jiffies + 1 * HZ;
2609+ while (time_before(jiffies, timeout)) {
2610+ ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL, 0x00);
2611+ if (ret < 0)
2612+ return ret;
2613+
2614+ if ((ret & is_reset) == is_reset)
2615+ break;
2616+ usleep_range(1000, 2000);
2617+ }
2618+ if (time_after(jiffies, timeout))
2619+ ret = -ETIMEDOUT;
2620+ else
2621+ ret = 0;
2622+
2623+ return ret;
2624+}
2625+
22972626 static int mv88e6xxx_power_on_serdes(struct mv88e6xxx_priv_state *ps)
22982627 {
22992628 int ret;
@@ -2313,14 +2642,12 @@ static int mv88e6xxx_power_on_serdes(struct mv88e6xxx_priv_state *ps) · 13 unmodified lines
23132642 return ret;
23142643 }
23152644
2316−static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
2645+static int mv88e6xxx_setup_port(struct mv88e6xxx_priv_state *ps, int port)
23172646 {
2318− struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
2647+ struct dsa_switch *ds = ps->ds;
23192648 int ret;
23202649 u16 reg;
23212650
2322− mutex_lock(&ps->smi_mutex);
2323−
23242651 if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) ||
23252652 mv88e6xxx_6165_family(ps) || mv88e6xxx_6097_family(ps) ||
23262653 mv88e6xxx_6185_family(ps) || mv88e6xxx_6095_family(ps) ||
@@ -2349,7 +2676,7 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) · 22 unmodified lines
23492676 ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
23502677 PORT_PCS_CTRL, reg);
23512678 if (ret)
2352− goto abort;
2679+ return ret;
23532680 }
23542681
23552682 /* Port Control: disable Drop-on-Unlock, disable Drop-on-Lock,
@@ -2413,7 +2740,7 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) · 57 unmodified lines
24132740 ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
24142741 PORT_CONTROL, reg);
24152742 if (ret)
2416− goto abort;
2743+ return ret;
24172744 }
24182745
24192746 /* If this port is connected to a SerDes, make sure the SerDes is not
@@ -2422,14 +2749,14 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) · 2 unmodified lines
24222749 if (mv88e6xxx_6352_family(ps)) {
24232750 ret = _mv88e6xxx_reg_read(ps, REG_PORT(port), PORT_STATUS);
24242751 if (ret < 0)
2425− goto abort;
2752+ return ret;
24262753 ret &= PORT_STATUS_CMODE_MASK;
24272754 if ((ret == PORT_STATUS_CMODE_100BASE_X) ||
24282755 (ret == PORT_STATUS_CMODE_1000BASE_X) ||
24292756 (ret == PORT_STATUS_CMODE_SGMII)) {
24302757 ret = mv88e6xxx_power_on_serdes(ps);
24312758 if (ret < 0)
2432− goto abort;
2759+ return ret;
24332760 }
24342761 }
24352762
@@ -2466,7 +2793,7 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) · 30 unmodified lines
24662793 ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
24672794 PORT_CONTROL_2, reg);
24682795 if (ret)
2469− goto abort;
2796+ return ret;
24702797 }
24712798
24722799 /* Port Association Vector: when learning source addresses
@@ -2481,13 +2808,13 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) · 8 unmodified lines
24812808
24822809 ret = _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_ASSOC_VECTOR, reg);
24832810 if (ret)
2484− goto abort;
2811+ return ret;
24852812
24862813 /* Egress rate control 2: disable egress rate control. */
24872814 ret = _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_RATE_CONTROL_2,
24882815 0x0000);
24892816 if (ret)
2490− goto abort;
2817+ return ret;
24912818
24922819 if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) ||
24932820 mv88e6xxx_6165_family(ps) || mv88e6xxx_6097_family(ps) ||
@@ -2499,7 +2826,7 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) · 5 unmodified lines
24992826 ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
25002827 PORT_PAUSE_CTRL, 0x0000);
25012828 if (ret)
2502− goto abort;
2829+ return ret;
25032830
25042831 /* Port ATU control: disable limiting the number of
25052832 * address database entries that this port is allowed
@@ -2513,7 +2840,7 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) · 7 unmodified lines
25132840 ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
25142841 PORT_PRI_OVERRIDE, 0x0000);
25152842 if (ret)
2516− goto abort;
2843+ return ret;
25172844
25182845 /* Port Ethertype: use the Ethertype DSA Ethertype
25192846 * value.
@@ -2521,14 +2848,14 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) · 1 unmodified line
25212848 ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
25222849 PORT_ETH_TYPE, ETH_P_EDSA);
25232850 if (ret)
2524− goto abort;
2851+ return ret;
25252852 /* Tag Remap: use an identity 802.1p prio -> switch
25262853 * prio mapping.
25272854 */
25282855 ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
25292856 PORT_TAG_REGMAP_0123, 0x3210);
25302857 if (ret)
2531− goto abort;
2858+ return ret;
25322859
25332860 /* Tag Remap 2: use an identity 802.1p prio -> switch
25342861 * prio mapping.
@@ -2536,7 +2863,7 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) · 1 unmodified line
25362863 ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
25372864 PORT_TAG_REGMAP_4567, 0x7654);
25382865 if (ret)
2539− goto abort;
2866+ return ret;
25402867 }
25412868
25422869 if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) ||
@@ -2547,7 +2874,7 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) · 4 unmodified lines
25472874 ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
25482875 PORT_RATE_CONTROL, 0x0001);
25492876 if (ret)
2550− goto abort;
2877+ return ret;
25512878 }
25522879
25532880 /* Port Control 1: disable trunking, disable sending
@@ -2555,7 +2882,7 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) · 1 unmodified line
25552882 */
25562883 ret = _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_CONTROL_1, 0x0000);
25572884 if (ret)
2558− goto abort;
2885+ return ret;
25592886
25602887 /* Port based VLAN map: give each port the same default address
25612888 * database, and allow bidirectional communication between the
@@ -2563,52 +2890,60 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) · 1 unmodified line
25632890 */
25642891 ret = _mv88e6xxx_port_fid_set(ps, port, 0);
25652892 if (ret)
2566− goto abort;
2893+ return ret;
25672894
25682895 ret = _mv88e6xxx_port_based_vlan_map(ps, port);
25692896 if (ret)
2570− goto abort;
2897+ return ret;
25712898
25722899 /* Default VLAN ID and priority: don't set a default VLAN
25732900 * ID, and set the default packet priority to zero.
25742901 */
25752902 ret = _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_DEFAULT_VLAN,
25762903 0x0000);
2577−abort:
2578− mutex_unlock(&ps->smi_mutex);
2579− return ret;
2580−}
2581−
2582−int mv88e6xxx_setup_ports(struct dsa_switch *ds)
2583−{
2584− struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
2585− int ret;
2586− int i;
2904+ if (ret)
2905+ return ret;
25872906
2588− for (i = 0; i < ps->info->num_ports; i++) {
2589− ret = mv88e6xxx_setup_port(ds, i);
2590− if (ret < 0)
2591− return ret;
2592− }
25932907 return 0;
25942908 }
25952909
2596−int mv88e6xxx_setup_common(struct mv88e6xxx_priv_state *ps)
2910+static int mv88e6xxx_setup_global(struct mv88e6xxx_priv_state *ps)
25972911 {
2598− mutex_init(&ps->smi_mutex);
2912+ struct dsa_switch *ds = ps->ds;
2913+ u32 upstream_port = dsa_upstream_port(ds);
2914+ u16 reg;
2915+ int err;
2916+ int i;
25992917
2600− INIT_WORK(&ps->bridge_work, mv88e6xxx_bridge_work);
2918+ /* Enable the PHY Polling Unit if present, don't discard any packets,
2919+ * and mask all interrupt sources.
2920+ */
2921+ reg = 0;
2922+ if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_PPU) ||
2923+ mv88e6xxx_has(ps, MV88E6XXX_FLAG_PPU_ACTIVE))
2924+ reg |= GLOBAL_CONTROL_PPU_ENABLE;
26012925
2602− return 0;
2603−}
2926+ err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL, reg);
2927+ if (err)
2928+ return err;
26042929
2605−int mv88e6xxx_setup_global(struct dsa_switch *ds)
2606−{
2607− struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
2608− int err;
2609− int i;
2930+ /* Configure the upstream port, and configure it as the port to which
2931+ * ingress and egress and ARP monitor frames are to be sent.
2932+ */
2933+ reg = upstream_port << GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT |
2934+ upstream_port << GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT |
2935+ upstream_port << GLOBAL_MONITOR_CONTROL_ARP_SHIFT;
2936+ err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_MONITOR_CONTROL, reg);
2937+ if (err)
2938+ return err;
2939+
2940+ /* Disable remote management, and set the switch's DSA device number. */
2941+ err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL_2,
2942+ GLOBAL_CONTROL_2_MULTIPLE_CASCADE |
2943+ (ds->index & 0x1f));
2944+ if (err)
2945+ return err;
26102946
2611− mutex_lock(&ps->smi_mutex);
26122947 /* Set the default address aging time to 5 minutes, and
26132948 * enable address learn messages to be sent to all message
26142949 * ports.
@@ -2616,45 +2951,45 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds) · 1 unmodified line
26162951 err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_ATU_CONTROL,
26172952 0x0140 | GLOBAL_ATU_CONTROL_LEARN2ALL);
26182953 if (err)
2619− goto unlock;
2954+ return err;
26202955
26212956 /* Configure the IP ToS mapping registers. */
26222957 err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_0, 0x0000);
26232958 if (err)
2624− goto unlock;
2959+ return err;
26252960 err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_1, 0x0000);
26262961 if (err)
2627− goto unlock;
2962+ return err;
26282963 err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_2, 0x5555);
26292964 if (err)
2630− goto unlock;
2965+ return err;
26312966 err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_3, 0x5555);
26322967 if (err)
2633− goto unlock;
2968+ return err;
26342969 err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_4, 0xaaaa);
26352970 if (err)
2636− goto unlock;
2971+ return err;
26372972 err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_5, 0xaaaa);
26382973 if (err)
2639− goto unlock;
2974+ return err;
26402975 err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_6, 0xffff);
26412976 if (err)
2642− goto unlock;
2977+ return err;
26432978 err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_7, 0xffff);
26442979 if (err)
2645− goto unlock;
2980+ return err;
26462981
26472982 /* Configure the IEEE 802.1p priority mapping register. */
26482983 err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IEEE_PRI, 0xfa41);
26492984 if (err)
2650− goto unlock;
2985+ return err;
26512986
26522987 /* Send all frames with destination addresses matching
26532988 * 01:80:c2:00:00:0x to the CPU port.
26542989 */
26552990 err = _mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_MGMT_EN_0X, 0xffff);
26562991 if (err)
2657− goto unlock;
2992+ return err;
26582993
26592994 /* Ignore removed tag data on doubly tagged packets, disable
26602995 * flow control messages, force flow control priority to the
@@ -2665,15 +3000,15 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds) · 4 unmodified lines
26653000 0x7 | GLOBAL2_SWITCH_MGMT_RSVD2CPU | 0x70 |
26663001 GLOBAL2_SWITCH_MGMT_FORCE_FLOW_CTRL_PRI);
26673002 if (err)
2668− goto unlock;
3003+ return err;
26693004
26703005 /* Program the DSA routing table. */
26713006 for (i = 0; i < 32; i++) {
26723007 int nexthop = 0x1f;
26733008
2674− if (ds->pd->rtable &&
2675− i != ds->index && i < ds->dst->pd->nr_chips)
2676− nexthop = ds->pd->rtable[i] & 0x1f;
3009+ if (ps->ds->pd->rtable &&
3010+ i != ps->ds->index && i < ps->ds->dst->pd->nr_chips)
3011+ nexthop = ps->ds->pd->rtable[i] & 0x1f;
26773012
26783013 err = _mv88e6xxx_reg_write(
26793014 ps, REG_GLOBAL2,
@@ -2681,7 +3016,7 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds) · 1 unmodified line
26813016 GLOBAL2_DEVICE_MAPPING_UPDATE |
26823017 (i << GLOBAL2_DEVICE_MAPPING_TARGET_SHIFT) | nexthop);
26833018 if (err)
2684− goto unlock;
3019+ return err;
26853020 }
26863021
26873022 /* Clear all trunk masks. */
@@ -2691,7 +3026,7 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds) · 3 unmodified lines
26913026 (i << GLOBAL2_TRUNK_MASK_NUM_SHIFT) |
26923027 ((1 << ps->info->num_ports) - 1));
26933028 if (err)
2694− goto unlock;
3029+ return err;
26953030 }
26963031
26973032 /* Clear all trunk mappings. */
@@ -2702,7 +3037,7 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds) · 4 unmodified lines
27023037 GLOBAL2_TRUNK_MAPPING_UPDATE |
27033038 (i << GLOBAL2_TRUNK_MAPPING_ID_SHIFT));
27043039 if (err)
2705− goto unlock;
3040+ return err;
27063041 }
27073042
27083043 if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) ||
@@ -2714,7 +3049,7 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds) · 5 unmodified lines
27143049 err = _mv88e6xxx_reg_write(ps, REG_GLOBAL2,
27153050 GLOBAL2_MGMT_EN_2X, 0xffff);
27163051 if (err)
2717− goto unlock;
3052+ return err;
27183053
27193054 /* Initialise cross-chip port VLAN table to reset
27203055 * defaults.
@@ -2722,7 +3057,7 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds) · 1 unmodified line
27223057 err = _mv88e6xxx_reg_write(ps, REG_GLOBAL2,
27233058 GLOBAL2_PVT_ADDR, 0x9000);
27243059 if (err)
2725− goto unlock;
3060+ return err;
27263061
27273062 /* Clear the priority override table. */
27283063 for (i = 0; i < 16; i++) {
@@ -2730,7 +3065,7 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds) · 1 unmodified line
27303065 GLOBAL2_PRIO_OVERRIDE,
27313066 0x8000 | (i << 8));
27323067 if (err)
2733− goto unlock;
3068+ return err;
27343069 }
27353070 }
27363071
@@ -2747,7 +3082,7 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds) · 10 unmodified lines
27473082 GLOBAL2_INGRESS_OP,
27483083 0x9000 | (i << 8));
27493084 if (err)
2750− goto unlock;
3085+ return err;
27513086 }
27523087 }
27533088
@@ -2755,89 +3090,64 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds) · 1 unmodified line
27553090 err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_STATS_OP,
27563091 GLOBAL_STATS_OP_FLUSH_ALL);
27573092 if (err)
2758− goto unlock;
3093+ return err;
27593094
27603095 /* Wait for the flush to complete. */
27613096 err = _mv88e6xxx_stats_wait(ps);
2762− if (err < 0)
2763− goto unlock;
3097+ if (err)
3098+ return err;
27643099
27653100 /* Clear all ATU entries */
27663101 err = _mv88e6xxx_atu_flush(ps, 0, true);
2767− if (err < 0)
2768− goto unlock;
3102+ if (err)
3103+ return err;
27693104
27703105 /* Clear all the VTU and STU entries */
27713106 err = _mv88e6xxx_vtu_stu_flush(ps);
2772−unlock:
2773− mutex_unlock(&ps->smi_mutex);
3107+ if (err < 0)
3108+ return err;
27743109
27753110 return err;
27763111 }
27773112
2778−int mv88e6xxx_switch_reset(struct mv88e6xxx_priv_state *ps, bool ppu_active)
3113+static int mv88e6xxx_setup(struct dsa_switch *ds)
27793114 {
2780− u16 is_reset = (ppu_active ? 0x8800 : 0xc800);
2781− struct gpio_desc *gpiod = ps->ds->pd->reset;
2782− unsigned long timeout;
2783− int ret;
3115+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
3116+ int err;
27843117 int i;
27853118
2786− mutex_lock(&ps->smi_mutex);
3119+ ps->ds = ds;
27873120
2788− /* Set all ports to the disabled state. */
2789− for (i = 0; i < ps->info->num_ports; i++) {
2790− ret = _mv88e6xxx_reg_read(ps, REG_PORT(i), PORT_CONTROL);
2791− if (ret < 0)
2792− goto unlock;
3121+ mutex_init(&ps->smi_mutex);
27933122
2794− ret = _mv88e6xxx_reg_write(ps, REG_PORT(i), PORT_CONTROL,
2795− ret & 0xfffc);
2796− if (ret)
2797− goto unlock;
2798− }
3123+ INIT_WORK(&ps->bridge_work, mv88e6xxx_bridge_work);
27993124
2800− /* Wait for transmit queues to drain. */
2801− usleep_range(2000, 4000);
3125+ if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_EEPROM))
3126+ mutex_init(&ps->eeprom_mutex);
28023127
2803− /* If there is a gpio connected to the reset pin, toggle it */
2804− if (gpiod) {
2805− gpiod_set_value_cansleep(gpiod, 1);
2806− usleep_range(10000, 20000);
2807− gpiod_set_value_cansleep(gpiod, 0);
2808− usleep_range(10000, 20000);
2809− }
3128+ if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_PPU))
3129+ mv88e6xxx_ppu_state_init(ps);
28103130
2811− /* Reset the switch. Keep the PPU active if requested. The PPU
2812− * needs to be active to support indirect phy register access
2813− * through global registers 0x18 and 0x19.
2814− */
2815− if (ppu_active)
2816− ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, 0x04, 0xc000);
2817− else
2818− ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, 0x04, 0xc400);
2819− if (ret)
3131+ mutex_lock(&ps->smi_mutex);
3132+
3133+ err = mv88e6xxx_switch_reset(ps);
3134+ if (err)
28203135 goto unlock;
28213136
2822− /* Wait up to one second for reset to complete. */
2823− timeout = jiffies + 1 * HZ;
2824− while (time_before(jiffies, timeout)) {
2825− ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL, 0x00);
2826− if (ret < 0)
2827− goto unlock;
3137+ err = mv88e6xxx_setup_global(ps);
3138+ if (err)
3139+ goto unlock;
28283140
2829− if ((ret & is_reset) == is_reset)
2830− break;
2831− usleep_range(1000, 2000);
3141+ for (i = 0; i < ps->info->num_ports; i++) {
3142+ err = mv88e6xxx_setup_port(ps, i);
3143+ if (err)
3144+ goto unlock;
28323145 }
2833− if (time_after(jiffies, timeout))
2834− ret = -ETIMEDOUT;
2835− else
2836− ret = 0;
3146+
28373147 unlock:
28383148 mutex_unlock(&ps->smi_mutex);
28393149
2840− return ret;
3150+ return err;
28413151 }
28423152
28433153 int mv88e6xxx_phy_page_read(struct dsa_switch *ds, int port, int page, int reg)
@@ -2873,8 +3183,7 @@ static int mv88e6xxx_port_to_phy_addr(struct mv88e6xxx_priv_state *ps, · 29 unmodified lines
28733183 return -EINVAL;
28743184 }
28753185
2876−int
2877−mv88e6xxx_phy_read(struct dsa_switch *ds, int port, int regnum)
3186+static int mv88e6xxx_phy_read(struct dsa_switch *ds, int port, int regnum)
28783187 {
28793188 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
28803189 int addr = mv88e6xxx_port_to_phy_addr(ps, port);
@@ -2884,29 +3193,20 @@ mv88e6xxx_phy_read(struct dsa_switch *ds, int port, int regnum) · 3 unmodified lines
28843193 return 0xffff;
28853194
28863195 mutex_lock(&ps->smi_mutex);
2887− ret = _mv88e6xxx_phy_read(ps, addr, regnum);
2888− mutex_unlock(&ps->smi_mutex);
2889− return ret;
2890−}
2891−
2892−int
2893−mv88e6xxx_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val)
2894−{
2895− struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
2896− int addr = mv88e6xxx_port_to_phy_addr(ps, port);
2897− int ret;
28983196
2899− if (addr < 0)
2900− return 0xffff;
3197+ if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_PPU))
3198+ ret = mv88e6xxx_phy_read_ppu(ps, addr, regnum);
3199+ else if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_SMI_PHY))
3200+ ret = _mv88e6xxx_phy_read_indirect(ps, addr, regnum);
3201+ else
3202+ ret = _mv88e6xxx_phy_read(ps, addr, regnum);
29013203
2902− mutex_lock(&ps->smi_mutex);
2903− ret = _mv88e6xxx_phy_write(ps, addr, regnum, val);
29043204 mutex_unlock(&ps->smi_mutex);
29053205 return ret;
29063206 }
29073207
2908−int
2909−mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int port, int regnum)
3208+static int mv88e6xxx_phy_write(struct dsa_switch *ds, int port, int regnum,
3209+ u16 val)
29103210 {
29113211 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
29123212 int addr = mv88e6xxx_port_to_phy_addr(ps, port);
@@ -2916,24 +3216,14 @@ mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int port, int regnum) · 3 unmodified lines
29163216 return 0xffff;
29173217
29183218 mutex_lock(&ps->smi_mutex);
2919− ret = _mv88e6xxx_phy_read_indirect(ps, addr, regnum);
2920− mutex_unlock(&ps->smi_mutex);
2921− return ret;
2922−}
29233219
2924−int
2925−mv88e6xxx_phy_write_indirect(struct dsa_switch *ds, int port, int regnum,
2926− u16 val)
2927−{
2928− struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
2929− int addr = mv88e6xxx_port_to_phy_addr(ps, port);
2930− int ret;
2931−
2932− if (addr < 0)
2933− return addr;
3220+ if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_PPU))
3221+ ret = mv88e6xxx_phy_write_ppu(ps, addr, regnum, val);
3222+ else if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_SMI_PHY))
3223+ ret = _mv88e6xxx_phy_write_indirect(ps, addr, regnum, val);
3224+ else
3225+ ret = _mv88e6xxx_phy_write(ps, addr, regnum, val);
29343226
2935− mutex_lock(&ps->smi_mutex);
2936− ret = _mv88e6xxx_phy_write_indirect(ps, addr, regnum, val);
29373227 mutex_unlock(&ps->smi_mutex);
29383228 return ret;
29393229 }
@@ -3002,23 +3292,26 @@ static int mv88e63xx_get_temp(struct dsa_switch *ds, int *temp) · 62 unmodified lines
30023292 return 0;
30033293 }
30043294
3005−int mv88e6xxx_get_temp(struct dsa_switch *ds, int *temp)
3295+static int mv88e6xxx_get_temp(struct dsa_switch *ds, int *temp)
30063296 {
30073297 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
30083298
3299+ if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_TEMP))
3300+ return -EOPNOTSUPP;
3301+
30093302 if (mv88e6xxx_6320_family(ps) || mv88e6xxx_6352_family(ps))
30103303 return mv88e63xx_get_temp(ds, temp);
30113304
30123305 return mv88e61xx_get_temp(ds, temp);
30133306 }
30143307
3015−int mv88e6xxx_get_temp_limit(struct dsa_switch *ds, int *temp)
3308+static int mv88e6xxx_get_temp_limit(struct dsa_switch *ds, int *temp)
30163309 {
30173310 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
30183311 int phy = mv88e6xxx_6320_family(ps) ? 3 : 0;
30193312 int ret;
30203313
3021− if (!mv88e6xxx_6320_family(ps) && !mv88e6xxx_6352_family(ps))
3314+ if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_TEMP_LIMIT))
30223315 return -EOPNOTSUPP;
30233316
30243317 *temp = 0;
@@ -3032,13 +3325,13 @@ int mv88e6xxx_get_temp_limit(struct dsa_switch *ds, int *temp) · 7 unmodified lines
30323325 return 0;
30333326 }
30343327
3035−int mv88e6xxx_set_temp_limit(struct dsa_switch *ds, int temp)
3328+static int mv88e6xxx_set_temp_limit(struct dsa_switch *ds, int temp)
30363329 {
30373330 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
30383331 int phy = mv88e6xxx_6320_family(ps) ? 3 : 0;
30393332 int ret;
30403333
3041− if (!mv88e6xxx_6320_family(ps) && !mv88e6xxx_6352_family(ps))
3334+ if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_TEMP_LIMIT))
30423335 return -EOPNOTSUPP;
30433336
30443337 ret = mv88e6xxx_phy_page_read(ds, phy, 6, 26);
@@ -3049,13 +3342,13 @@ int mv88e6xxx_set_temp_limit(struct dsa_switch *ds, int temp) · 4 unmodified lines
30493342 (ret & 0xe0ff) | (temp << 8));
30503343 }
30513344
3052−int mv88e6xxx_get_temp_alarm(struct dsa_switch *ds, bool *alarm)
3345+static int mv88e6xxx_get_temp_alarm(struct dsa_switch *ds, bool *alarm)
30533346 {
30543347 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
30553348 int phy = mv88e6xxx_6320_family(ps) ? 3 : 0;
30563349 int ret;
30573350
3058− if (!mv88e6xxx_6320_family(ps) && !mv88e6xxx_6352_family(ps))
3351+ if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_TEMP_LIMIT))
30593352 return -EOPNOTSUPP;
30603353
30613354 *alarm = false;
@@ -3070,6 +3363,161 @@ int mv88e6xxx_get_temp_alarm(struct dsa_switch *ds, bool *alarm) · 8 unmodified lines
30703363 }
30713364 #endif /* CONFIG_NET_DSA_HWMON */
30723365
3366+static const struct mv88e6xxx_info mv88e6xxx_table[] = {
3367+ [MV88E6085] = {
3368+ .prod_num = PORT_SWITCH_ID_PROD_NUM_6085,
3369+ .family = MV88E6XXX_FAMILY_6097,
3370+ .name = "Marvell 88E6085",
3371+ .num_databases = 4096,
3372+ .num_ports = 10,
3373+ .flags = MV88E6XXX_FLAGS_FAMILY_6097,
3374+ },
3375+
3376+ [MV88E6095] = {
3377+ .prod_num = PORT_SWITCH_ID_PROD_NUM_6095,
3378+ .family = MV88E6XXX_FAMILY_6095,
3379+ .name = "Marvell 88E6095/88E6095F",
3380+ .num_databases = 256,
3381+ .num_ports = 11,
3382+ .flags = MV88E6XXX_FLAGS_FAMILY_6095,
3383+ },
3384+
3385+ [MV88E6123] = {
3386+ .prod_num = PORT_SWITCH_ID_PROD_NUM_6123,
3387+ .family = MV88E6XXX_FAMILY_6165,
3388+ .name = "Marvell 88E6123",
3389+ .num_databases = 4096,
3390+ .num_ports = 3,
3391+ .flags = MV88E6XXX_FLAGS_FAMILY_6165,
3392+ },
3393+
3394+ [MV88E6131] = {
3395+ .prod_num = PORT_SWITCH_ID_PROD_NUM_6131,
3396+ .family = MV88E6XXX_FAMILY_6185,
3397+ .name = "Marvell 88E6131",
3398+ .num_databases = 256,
3399+ .num_ports = 8,
3400+ .flags = MV88E6XXX_FLAGS_FAMILY_6185,
3401+ },
3402+
3403+ [MV88E6161] = {
3404+ .prod_num = PORT_SWITCH_ID_PROD_NUM_6161,
3405+ .family = MV88E6XXX_FAMILY_6165,
3406+ .name = "Marvell 88E6161",
3407+ .num_databases = 4096,
3408+ .num_ports = 6,
3409+ .flags = MV88E6XXX_FLAGS_FAMILY_6165,
3410+ },
3411+
3412+ [MV88E6165] = {
3413+ .prod_num = PORT_SWITCH_ID_PROD_NUM_6165,
3414+ .family = MV88E6XXX_FAMILY_6165,
3415+ .name = "Marvell 88E6165",
3416+ .num_databases = 4096,
3417+ .num_ports = 6,
3418+ .flags = MV88E6XXX_FLAGS_FAMILY_6165,
3419+ },
3420+
3421+ [MV88E6171] = {
3422+ .prod_num = PORT_SWITCH_ID_PROD_NUM_6171,
3423+ .family = MV88E6XXX_FAMILY_6351,
3424+ .name = "Marvell 88E6171",
3425+ .num_databases = 4096,
3426+ .num_ports = 7,
3427+ .flags = MV88E6XXX_FLAGS_FAMILY_6351,
3428+ },
3429+
3430+ [MV88E6172] = {
3431+ .prod_num = PORT_SWITCH_ID_PROD_NUM_6172,
3432+ .family = MV88E6XXX_FAMILY_6352,
3433+ .name = "Marvell 88E6172",
3434+ .num_databases = 4096,
3435+ .num_ports = 7,
3436+ .flags = MV88E6XXX_FLAGS_FAMILY_6352,
3437+ },
3438+
3439+ [MV88E6175] = {
3440+ .prod_num = PORT_SWITCH_ID_PROD_NUM_6175,
3441+ .family = MV88E6XXX_FAMILY_6351,
3442+ .name = "Marvell 88E6175",
3443+ .num_databases = 4096,
3444+ .num_ports = 7,
3445+ .flags = MV88E6XXX_FLAGS_FAMILY_6351,
3446+ },
3447+
3448+ [MV88E6176] = {
3449+ .prod_num = PORT_SWITCH_ID_PROD_NUM_6176,
3450+ .family = MV88E6XXX_FAMILY_6352,
3451+ .name = "Marvell 88E6176",
3452+ .num_databases = 4096,
3453+ .num_ports = 7,
3454+ .flags = MV88E6XXX_FLAGS_FAMILY_6352,
3455+ },
3456+
3457+ [MV88E6185] = {
3458+ .prod_num = PORT_SWITCH_ID_PROD_NUM_6185,
3459+ .family = MV88E6XXX_FAMILY_6185,
3460+ .name = "Marvell 88E6185",
3461+ .num_databases = 256,
3462+ .num_ports = 10,
3463+ .flags = MV88E6XXX_FLAGS_FAMILY_6185,
3464+ },
3465+
3466+ [MV88E6240] = {
3467+ .prod_num = PORT_SWITCH_ID_PROD_NUM_6240,
3468+ .family = MV88E6XXX_FAMILY_6352,
3469+ .name = "Marvell 88E6240",
3470+ .num_databases = 4096,
3471+ .num_ports = 7,
3472+ .flags = MV88E6XXX_FLAGS_FAMILY_6352,
3473+ },
3474+
3475+ [MV88E6320] = {
3476+ .prod_num = PORT_SWITCH_ID_PROD_NUM_6320,
3477+ .family = MV88E6XXX_FAMILY_6320,
3478+ .name = "Marvell 88E6320",
3479+ .num_databases = 4096,
3480+ .num_ports = 7,
3481+ .flags = MV88E6XXX_FLAGS_FAMILY_6320,
3482+ },
3483+
3484+ [MV88E6321] = {
3485+ .prod_num = PORT_SWITCH_ID_PROD_NUM_6321,
3486+ .family = MV88E6XXX_FAMILY_6320,
3487+ .name = "Marvell 88E6321",
3488+ .num_databases = 4096,
3489+ .num_ports = 7,
3490+ .flags = MV88E6XXX_FLAGS_FAMILY_6320,
3491+ },
3492+
3493+ [MV88E6350] = {
3494+ .prod_num = PORT_SWITCH_ID_PROD_NUM_6350,
3495+ .family = MV88E6XXX_FAMILY_6351,
3496+ .name = "Marvell 88E6350",
3497+ .num_databases = 4096,
3498+ .num_ports = 7,
3499+ .flags = MV88E6XXX_FLAGS_FAMILY_6351,
3500+ },
3501+
3502+ [MV88E6351] = {
3503+ .prod_num = PORT_SWITCH_ID_PROD_NUM_6351,
3504+ .family = MV88E6XXX_FAMILY_6351,
3505+ .name = "Marvell 88E6351",
3506+ .num_databases = 4096,
3507+ .num_ports = 7,
3508+ .flags = MV88E6XXX_FLAGS_FAMILY_6351,
3509+ },
3510+
3511+ [MV88E6352] = {
3512+ .prod_num = PORT_SWITCH_ID_PROD_NUM_6352,
3513+ .family = MV88E6XXX_FAMILY_6352,
3514+ .name = "Marvell 88E6352",
3515+ .num_databases = 4096,
3516+ .num_ports = 7,
3517+ .flags = MV88E6XXX_FLAGS_FAMILY_6352,
3518+ },
3519+};
3520+
30733521 static const struct mv88e6xxx_info *
30743522 mv88e6xxx_lookup_info(unsigned int prod_num, const struct mv88e6xxx_info *table,
30753523 unsigned int num)
@@ -3083,10 +3531,9 @@ mv88e6xxx_lookup_info(unsigned int prod_num, const struct mv88e6xxx_info *table, · 7 unmodified lines
30833531 return NULL;
30843532 }
30853533
3086−const char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev,
3087− int sw_addr, void **priv,
3088− const struct mv88e6xxx_info *table,
3089− unsigned int num)
3534+static const char *mv88e6xxx_probe(struct device *dsa_dev,
3535+ struct device *host_dev, int sw_addr,
3536+ void **priv)
30903537 {
30913538 const struct mv88e6xxx_info *info;
30923539 struct mv88e6xxx_priv_state *ps;
@@ -3105,7 +3552,8 @@ const char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev, · 12 unmodified lines
31053552 prod_num = (id & 0xfff0) >> 4;
31063553 rev = id & 0x000f;
31073554
3108− info = mv88e6xxx_lookup_info(prod_num, table, num);
3555+ info = mv88e6xxx_lookup_info(prod_num, mv88e6xxx_table,
3556+ ARRAY_SIZE(mv88e6xxx_table));
31093557 if (!info)
31103558 return NULL;
31113559
@@ -3127,41 +3575,73 @@ const char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev, · 15 unmodified lines
31273575 return name;
31283576 }
31293577
3578+struct dsa_switch_driver mv88e6xxx_switch_driver = {
3579+ .tag_protocol = DSA_TAG_PROTO_EDSA,
3580+ .probe = mv88e6xxx_probe,
3581+ .setup = mv88e6xxx_setup,
3582+ .set_addr = mv88e6xxx_set_addr,
3583+ .phy_read = mv88e6xxx_phy_read,
3584+ .phy_write = mv88e6xxx_phy_write,
3585+ .adjust_link = mv88e6xxx_adjust_link,
3586+ .get_strings = mv88e6xxx_get_strings,
3587+ .get_ethtool_stats = mv88e6xxx_get_ethtool_stats,
3588+ .get_sset_count = mv88e6xxx_get_sset_count,
3589+ .set_eee = mv88e6xxx_set_eee,
3590+ .get_eee = mv88e6xxx_get_eee,
3591+#ifdef CONFIG_NET_DSA_HWMON
3592+ .get_temp = mv88e6xxx_get_temp,
3593+ .get_temp_limit = mv88e6xxx_get_temp_limit,
3594+ .set_temp_limit = mv88e6xxx_set_temp_limit,
3595+ .get_temp_alarm = mv88e6xxx_get_temp_alarm,
3596+#endif
3597+ .get_eeprom = mv88e6xxx_get_eeprom,
3598+ .set_eeprom = mv88e6xxx_set_eeprom,
3599+ .get_regs_len = mv88e6xxx_get_regs_len,
3600+ .get_regs = mv88e6xxx_get_regs,
3601+ .port_bridge_join = mv88e6xxx_port_bridge_join,
3602+ .port_bridge_leave = mv88e6xxx_port_bridge_leave,
3603+ .port_stp_state_set = mv88e6xxx_port_stp_state_set,
3604+ .port_vlan_filtering = mv88e6xxx_port_vlan_filtering,
3605+ .port_vlan_prepare = mv88e6xxx_port_vlan_prepare,
3606+ .port_vlan_add = mv88e6xxx_port_vlan_add,
3607+ .port_vlan_del = mv88e6xxx_port_vlan_del,
3608+ .port_vlan_dump = mv88e6xxx_port_vlan_dump,
3609+ .port_fdb_prepare = mv88e6xxx_port_fdb_prepare,
3610+ .port_fdb_add = mv88e6xxx_port_fdb_add,
3611+ .port_fdb_del = mv88e6xxx_port_fdb_del,
3612+ .port_fdb_dump = mv88e6xxx_port_fdb_dump,
3613+};
3614+
31303615 static int __init mv88e6xxx_init(void)
31313616 {
3132−#if IS_ENABLED(CONFIG_NET_DSA_MV88E6131)
3133− register_switch_driver(&mv88e6131_switch_driver);
3134−#endif
3135−#if IS_ENABLED(CONFIG_NET_DSA_MV88E6123)
3136− register_switch_driver(&mv88e6123_switch_driver);
3137−#endif
3138−#if IS_ENABLED(CONFIG_NET_DSA_MV88E6352)
3139− register_switch_driver(&mv88e6352_switch_driver);
3140−#endif
3141−#if IS_ENABLED(CONFIG_NET_DSA_MV88E6171)
3142− register_switch_driver(&mv88e6171_switch_driver);
3143−#endif
3617+ register_switch_driver(&mv88e6xxx_switch_driver);
3618+
31443619 return 0;
31453620 }
31463621 module_init(mv88e6xxx_init);
31473622
31483623 static void __exit mv88e6xxx_cleanup(void)
31493624 {
3150−#if IS_ENABLED(CONFIG_NET_DSA_MV88E6171)
3151− unregister_switch_driver(&mv88e6171_switch_driver);
3152−#endif
3153−#if IS_ENABLED(CONFIG_NET_DSA_MV88E6352)
3154− unregister_switch_driver(&mv88e6352_switch_driver);
3155−#endif
3156−#if IS_ENABLED(CONFIG_NET_DSA_MV88E6123)
3157− unregister_switch_driver(&mv88e6123_switch_driver);
3158−#endif
3159−#if IS_ENABLED(CONFIG_NET_DSA_MV88E6131)
3160− unregister_switch_driver(&mv88e6131_switch_driver);
3161−#endif
3625+ unregister_switch_driver(&mv88e6xxx_switch_driver);
31623626 }
31633627 module_exit(mv88e6xxx_cleanup);
31643628
3629+MODULE_ALIAS("platform:mv88e6085");
3630+MODULE_ALIAS("platform:mv88e6095");
3631+MODULE_ALIAS("platform:mv88e6095f");
3632+MODULE_ALIAS("platform:mv88e6123");
3633+MODULE_ALIAS("platform:mv88e6131");
3634+MODULE_ALIAS("platform:mv88e6161");
3635+MODULE_ALIAS("platform:mv88e6165");
3636+MODULE_ALIAS("platform:mv88e6171");
3637+MODULE_ALIAS("platform:mv88e6172");
3638+MODULE_ALIAS("platform:mv88e6175");
3639+MODULE_ALIAS("platform:mv88e6176");
3640+MODULE_ALIAS("platform:mv88e6320");
3641+MODULE_ALIAS("platform:mv88e6321");
3642+MODULE_ALIAS("platform:mv88e6350");
3643+MODULE_ALIAS("platform:mv88e6351");
3644+MODULE_ALIAS("platform:mv88e6352");
31653645 MODULE_AUTHOR("Lennert Buytenhek <buytenh@wantstofly.org>");
31663646 MODULE_DESCRIPTION("Driver for Marvell 88E6XXX ethernet switch chips");
31673647 MODULE_LICENSE("GPL");
drivers/net/dsa/mv88e6xxx.h+156−83
@@ -338,6 +338,27 @@ · 337 unmodified lines
338338
339339 #define MV88E6XXX_N_FID 4096
340340
341+/* List of supported models */
342+enum mv88e6xxx_model {
343+ MV88E6085,
344+ MV88E6095,
345+ MV88E6123,
346+ MV88E6131,
347+ MV88E6161,
348+ MV88E6165,
349+ MV88E6171,
350+ MV88E6172,
351+ MV88E6175,
352+ MV88E6176,
353+ MV88E6185,
354+ MV88E6240,
355+ MV88E6320,
356+ MV88E6321,
357+ MV88E6350,
358+ MV88E6351,
359+ MV88E6352,
360+};
361+
341362 enum mv88e6xxx_family {
342363 MV88E6XXX_FAMILY_NONE,
343364 MV88E6XXX_FAMILY_6065, /* 6031 6035 6061 6065 */
@@ -350,12 +371,142 @@ enum mv88e6xxx_family { · 6 unmodified lines
350371 MV88E6XXX_FAMILY_6352, /* 6172 6176 6240 6352 */
351372 };
352373
374+enum mv88e6xxx_cap {
375+ /* Address Translation Unit.
376+ * The ATU is used to lookup and learn MAC addresses. See GLOBAL_ATU_OP.
377+ */
378+ MV88E6XXX_CAP_ATU,
379+
380+ /* Energy Efficient Ethernet.
381+ */
382+ MV88E6XXX_CAP_EEE,
383+
384+ /* EEPROM Command and Data registers.
385+ * See GLOBAL2_EEPROM_OP and GLOBAL2_EEPROM_DATA.
386+ */
387+ MV88E6XXX_CAP_EEPROM,
388+
389+ /* Port State Filtering for 802.1D Spanning Tree.
390+ * See PORT_CONTROL_STATE_* values in the PORT_CONTROL register.
391+ */
392+ MV88E6XXX_CAP_PORTSTATE,
393+
394+ /* PHY Polling Unit.
395+ * See GLOBAL_CONTROL_PPU_ENABLE and GLOBAL_STATUS_PPU_POLLING.
396+ */
397+ MV88E6XXX_CAP_PPU,
398+ MV88E6XXX_CAP_PPU_ACTIVE,
399+
400+ /* SMI PHY Command and Data registers.
401+ * This requires an indirect access to PHY registers through
402+ * GLOBAL2_SMI_OP, otherwise direct access to PHY registers is done.
403+ */
404+ MV88E6XXX_CAP_SMI_PHY,
405+
406+ /* Switch MAC/WoL/WoF register.
407+ * This requires an indirect access to set the switch MAC address
408+ * through GLOBAL2_SWITCH_MAC, otherwise GLOBAL_MAC_01, GLOBAL_MAC_23,
409+ * and GLOBAL_MAC_45 are used with a direct access.
410+ */
411+ MV88E6XXX_CAP_SWITCH_MAC_WOL_WOF,
412+
413+ /* Internal temperature sensor.
414+ * Available from any enabled port's PHY register 26, page 6.
415+ */
416+ MV88E6XXX_CAP_TEMP,
417+ MV88E6XXX_CAP_TEMP_LIMIT,
418+
419+ /* In-chip Port Based VLANs.
420+ * Each port VLANTable register (see PORT_BASE_VLAN) is used to restrict
421+ * the output (or egress) ports to which it is allowed to send frames.
422+ */
423+ MV88E6XXX_CAP_VLANTABLE,
424+
425+ /* VLAN Table Unit.
426+ * The VTU is used to program 802.1Q VLANs. See GLOBAL_VTU_OP.
427+ */
428+ MV88E6XXX_CAP_VTU,
429+};
430+
431+/* Bitmask of capabilities */
432+#define MV88E6XXX_FLAG_ATU BIT(MV88E6XXX_CAP_ATU)
433+#define MV88E6XXX_FLAG_EEE BIT(MV88E6XXX_CAP_EEE)
434+#define MV88E6XXX_FLAG_EEPROM BIT(MV88E6XXX_CAP_EEPROM)
435+#define MV88E6XXX_FLAG_PORTSTATE BIT(MV88E6XXX_CAP_PORTSTATE)
436+#define MV88E6XXX_FLAG_PPU BIT(MV88E6XXX_CAP_PPU)
437+#define MV88E6XXX_FLAG_PPU_ACTIVE BIT(MV88E6XXX_CAP_PPU_ACTIVE)
438+#define MV88E6XXX_FLAG_SMI_PHY BIT(MV88E6XXX_CAP_SMI_PHY)
439+#define MV88E6XXX_FLAG_SWITCH_MAC BIT(MV88E6XXX_CAP_SWITCH_MAC_WOL_WOF)
440+#define MV88E6XXX_FLAG_TEMP BIT(MV88E6XXX_CAP_TEMP)
441+#define MV88E6XXX_FLAG_TEMP_LIMIT BIT(MV88E6XXX_CAP_TEMP_LIMIT)
442+#define MV88E6XXX_FLAG_VLANTABLE BIT(MV88E6XXX_CAP_VLANTABLE)
443+#define MV88E6XXX_FLAG_VTU BIT(MV88E6XXX_CAP_VTU)
444+
445+#define MV88E6XXX_FLAGS_FAMILY_6095 \
446+ (MV88E6XXX_FLAG_ATU | \
447+ MV88E6XXX_FLAG_PPU | \
448+ MV88E6XXX_FLAG_VLANTABLE | \
449+ MV88E6XXX_FLAG_VTU)
450+
451+#define MV88E6XXX_FLAGS_FAMILY_6097 \
452+ (MV88E6XXX_FLAG_ATU | \
453+ MV88E6XXX_FLAG_PPU | \
454+ MV88E6XXX_FLAG_VLANTABLE | \
455+ MV88E6XXX_FLAG_VTU)
456+
457+#define MV88E6XXX_FLAGS_FAMILY_6165 \
458+ (MV88E6XXX_FLAG_SWITCH_MAC | \
459+ MV88E6XXX_FLAG_TEMP)
460+
461+#define MV88E6XXX_FLAGS_FAMILY_6185 \
462+ (MV88E6XXX_FLAG_ATU | \
463+ MV88E6XXX_FLAG_PPU | \
464+ MV88E6XXX_FLAG_VLANTABLE | \
465+ MV88E6XXX_FLAG_VTU)
466+
467+#define MV88E6XXX_FLAGS_FAMILY_6320 \
468+ (MV88E6XXX_FLAG_ATU | \
469+ MV88E6XXX_FLAG_EEE | \
470+ MV88E6XXX_FLAG_EEPROM | \
471+ MV88E6XXX_FLAG_PORTSTATE | \
472+ MV88E6XXX_FLAG_PPU_ACTIVE | \
473+ MV88E6XXX_FLAG_SMI_PHY | \
474+ MV88E6XXX_FLAG_SWITCH_MAC | \
475+ MV88E6XXX_FLAG_TEMP | \
476+ MV88E6XXX_FLAG_TEMP_LIMIT | \
477+ MV88E6XXX_FLAG_VLANTABLE | \
478+ MV88E6XXX_FLAG_VTU)
479+
480+#define MV88E6XXX_FLAGS_FAMILY_6351 \
481+ (MV88E6XXX_FLAG_ATU | \
482+ MV88E6XXX_FLAG_PORTSTATE | \
483+ MV88E6XXX_FLAG_PPU_ACTIVE | \
484+ MV88E6XXX_FLAG_SMI_PHY | \
485+ MV88E6XXX_FLAG_SWITCH_MAC | \
486+ MV88E6XXX_FLAG_TEMP | \
487+ MV88E6XXX_FLAG_VLANTABLE | \
488+ MV88E6XXX_FLAG_VTU)
489+
490+#define MV88E6XXX_FLAGS_FAMILY_6352 \
491+ (MV88E6XXX_FLAG_ATU | \
492+ MV88E6XXX_FLAG_EEE | \
493+ MV88E6XXX_FLAG_EEPROM | \
494+ MV88E6XXX_FLAG_PORTSTATE | \
495+ MV88E6XXX_FLAG_PPU_ACTIVE | \
496+ MV88E6XXX_FLAG_SMI_PHY | \
497+ MV88E6XXX_FLAG_SWITCH_MAC | \
498+ MV88E6XXX_FLAG_TEMP | \
499+ MV88E6XXX_FLAG_TEMP_LIMIT | \
500+ MV88E6XXX_FLAG_VLANTABLE | \
501+ MV88E6XXX_FLAG_VTU)
502+
353503 struct mv88e6xxx_info {
354504 enum mv88e6xxx_family family;
355505 u16 prod_num;
356506 const char *name;
357507 unsigned int num_databases;
358508 unsigned int num_ports;
509+ unsigned long flags;
359510 };
360511
361512 struct mv88e6xxx_atu_entry {
@@ -403,7 +554,6 @@ struct mv88e6xxx_priv_state { · 41 unmodified lines
403554 struct mii_bus *bus;
404555 int sw_addr;
405556
406−#ifdef CONFIG_NET_DSA_MV88E6XXX_NEED_PPU
407557 /* Handles automatic disabling and re-enabling of the PHY
408558 * polling unit.
409559 */
@@ -411,7 +561,6 @@ struct mv88e6xxx_priv_state { · 1 unmodified line
411561 int ppu_disabled;
412562 struct work_struct ppu_work;
413563 struct timer_list ppu_timer;
414−#endif
415564
416565 /* This mutex serialises access to the statistics unit.
417566 * Hold this mutex over snapshot + dump sequences.
@@ -449,86 +598,10 @@ struct mv88e6xxx_hw_stat { · 31 unmodified lines
449598 enum stat_type type;
450599 };
451600
452−int mv88e6xxx_switch_reset(struct mv88e6xxx_priv_state *ps, bool ppu_active);
453−const char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev,
454− int sw_addr, void **priv,
455− const struct mv88e6xxx_info *table,
456− unsigned int num);
457−
458−int mv88e6xxx_setup_ports(struct dsa_switch *ds);
459−int mv88e6xxx_setup_common(struct mv88e6xxx_priv_state *ps);
460−int mv88e6xxx_setup_global(struct dsa_switch *ds);
461−int mv88e6xxx_reg_read(struct mv88e6xxx_priv_state *ps, int addr, int reg);
462−int mv88e6xxx_reg_write(struct mv88e6xxx_priv_state *ps, int addr,
463− int reg, u16 val);
464−int mv88e6xxx_set_addr_direct(struct dsa_switch *ds, u8 *addr);
465−int mv88e6xxx_set_addr_indirect(struct dsa_switch *ds, u8 *addr);
466−int mv88e6xxx_phy_read(struct dsa_switch *ds, int port, int regnum);
467−int mv88e6xxx_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val);
468−int mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int port, int regnum);
469−int mv88e6xxx_phy_write_indirect(struct dsa_switch *ds, int port, int regnum,
470− u16 val);
471−void mv88e6xxx_ppu_state_init(struct mv88e6xxx_priv_state *ps);
472−int mv88e6xxx_phy_read_ppu(struct dsa_switch *ds, int addr, int regnum);
473−int mv88e6xxx_phy_write_ppu(struct dsa_switch *ds, int addr,
474− int regnum, u16 val);
475−void mv88e6xxx_get_strings(struct dsa_switch *ds, int port, uint8_t *data);
476−void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, int port,
477− uint64_t *data);
478−int mv88e6xxx_get_sset_count(struct dsa_switch *ds);
479−int mv88e6xxx_get_sset_count_basic(struct dsa_switch *ds);
480−void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port,
481− struct phy_device *phydev);
482−int mv88e6xxx_get_regs_len(struct dsa_switch *ds, int port);
483−void mv88e6xxx_get_regs(struct dsa_switch *ds, int port,
484− struct ethtool_regs *regs, void *_p);
485−int mv88e6xxx_get_temp(struct dsa_switch *ds, int *temp);
486−int mv88e6xxx_get_temp_limit(struct dsa_switch *ds, int *temp);
487−int mv88e6xxx_set_temp_limit(struct dsa_switch *ds, int temp);
488−int mv88e6xxx_get_temp_alarm(struct dsa_switch *ds, bool *alarm);
489−int mv88e6xxx_eeprom_load_wait(struct dsa_switch *ds);
490−int mv88e6xxx_eeprom_busy_wait(struct dsa_switch *ds);
491−int mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int addr, int regnum);
492−int mv88e6xxx_phy_write_indirect(struct dsa_switch *ds, int addr, int regnum,
493− u16 val);
494−int mv88e6xxx_get_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e);
495−int mv88e6xxx_set_eee(struct dsa_switch *ds, int port,
496− struct phy_device *phydev, struct ethtool_eee *e);
497−int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port,
498− struct net_device *bridge);
499−void mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port);
500−void mv88e6xxx_port_stp_state_set(struct dsa_switch *ds, int port, u8 state);
501−int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port,
502− bool vlan_filtering);
503−int mv88e6xxx_port_vlan_prepare(struct dsa_switch *ds, int port,
504− const struct switchdev_obj_port_vlan *vlan,
505− struct switchdev_trans *trans);
506−void mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port,
507− const struct switchdev_obj_port_vlan *vlan,
508− struct switchdev_trans *trans);
509−int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port,
510− const struct switchdev_obj_port_vlan *vlan);
511−int mv88e6xxx_port_vlan_dump(struct dsa_switch *ds, int port,
512− struct switchdev_obj_port_vlan *vlan,
513− int (*cb)(struct switchdev_obj *obj));
514−int mv88e6xxx_port_fdb_prepare(struct dsa_switch *ds, int port,
515− const struct switchdev_obj_port_fdb *fdb,
516− struct switchdev_trans *trans);
517−void mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port,
518− const struct switchdev_obj_port_fdb *fdb,
519− struct switchdev_trans *trans);
520−int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port,
521− const struct switchdev_obj_port_fdb *fdb);
522−int mv88e6xxx_port_fdb_dump(struct dsa_switch *ds, int port,
523− struct switchdev_obj_port_fdb *fdb,
524− int (*cb)(struct switchdev_obj *obj));
525−int mv88e6xxx_phy_page_read(struct dsa_switch *ds, int port, int page, int reg);
526−int mv88e6xxx_phy_page_write(struct dsa_switch *ds, int port, int page,
527− int reg, int val);
528−
529−extern struct dsa_switch_driver mv88e6131_switch_driver;
530−extern struct dsa_switch_driver mv88e6123_switch_driver;
531−extern struct dsa_switch_driver mv88e6352_switch_driver;
532−extern struct dsa_switch_driver mv88e6171_switch_driver;
601+static inline bool mv88e6xxx_has(struct mv88e6xxx_priv_state *ps,
602+ unsigned long flags)
603+{
604+ return (ps->info->flags & flags) == flags;
605+}
533606
534607 #endif