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
91CONFIG_SATA_MV=y91CONFIG_SATA_MV=y
92CONFIG_NETDEVICES=y92CONFIG_NETDEVICES=y
93CONFIG_NET_DSA_MV88E6060=y93CONFIG_NET_DSA_MV88E6060=y
94CONFIG_NET_DSA_MV88E6131=y94CONFIG_NET_DSA_MV88E6XXX=y
95CONFIG_NET_DSA_MV88E6123=y
96CONFIG_NET_DSA_MV88E6171=y
97CONFIG_NET_DSA_MV88E6352=y
98CONFIG_MV643XX_ETH=y95CONFIG_MV643XX_ETH=y
99CONFIG_R8169=y96CONFIG_R8169=y
100CONFIG_MARVELL_PHY=y97CONFIG_MARVELL_PHY=y
arch/arm/configs/mvebu_v7_defconfig+1−1
@@ -66,7 +66,7 @@ CONFIG_SATA_AHCI=y · 65 unmodified lines
66CONFIG_AHCI_MVEBU=y66CONFIG_AHCI_MVEBU=y
67CONFIG_SATA_MV=y67CONFIG_SATA_MV=y
68CONFIG_NETDEVICES=y68CONFIG_NETDEVICES=y
69CONFIG_NET_DSA_MV88E6171=y69CONFIG_NET_DSA_MV88E6XXX=y
70CONFIG_MV643XX_ETH=y70CONFIG_MV643XX_ETH=y
71CONFIG_MVNETA=y71CONFIG_MVNETA=y
72CONFIG_MVPP2=y72CONFIG_MVPP2=y
arch/arm/configs/orion5x_defconfig+1−2
@@ -85,8 +85,7 @@ CONFIG_ATA=y · 84 unmodified lines
85CONFIG_SATA_MV=y85CONFIG_SATA_MV=y
86CONFIG_NETDEVICES=y86CONFIG_NETDEVICES=y
87CONFIG_MII=y87CONFIG_MII=y
88CONFIG_NET_DSA_MV88E6131=y88CONFIG_NET_DSA_MV88E6XXX=y
89CONFIG_NET_DSA_MV88E6123=y
90CONFIG_MV643XX_ETH=y89CONFIG_MV643XX_ETH=y
91CONFIG_MARVELL_PHY=y90CONFIG_MARVELL_PHY=y
92# CONFIG_INPUT_MOUSEDEV is not set91# CONFIG_INPUT_MOUSEDEV is not set
arch/tile/configs/tilegx_defconfig+1−2
@@ -221,8 +221,7 @@ CONFIG_NETCONSOLE_DYNAMIC=y · 220 unmodified lines
221CONFIG_TUN=y221CONFIG_TUN=y
222CONFIG_VETH=m222CONFIG_VETH=m
223CONFIG_NET_DSA_MV88E6060=y223CONFIG_NET_DSA_MV88E6060=y
224CONFIG_NET_DSA_MV88E6131=y224CONFIG_NET_DSA_MV88E6XXX=y
225CONFIG_NET_DSA_MV88E6123=y
226CONFIG_SKY2=y225CONFIG_SKY2=y
227CONFIG_PTP_1588_CLOCK_TILEGX=y226CONFIG_PTP_1588_CLOCK_TILEGX=y
228# CONFIG_WLAN is not set227# CONFIG_WLAN is not set
arch/tile/configs/tilepro_defconfig+1−2
@@ -340,8 +340,7 @@ CONFIG_NETCONSOLE_DYNAMIC=y · 339 unmodified lines
340CONFIG_TUN=y340CONFIG_TUN=y
341CONFIG_VETH=m341CONFIG_VETH=m
342CONFIG_NET_DSA_MV88E6060=y342CONFIG_NET_DSA_MV88E6060=y
343CONFIG_NET_DSA_MV88E6131=y343CONFIG_NET_DSA_MV88E6XXX=y
344CONFIG_NET_DSA_MV88E6123=y
345# CONFIG_NET_VENDOR_3COM is not set344# CONFIG_NET_VENDOR_3COM is not set
346CONFIG_E1000E=y345CONFIG_E1000E=y
347# CONFIG_WLAN is not set346# CONFIG_WLAN is not set
drivers/net/dsa/Kconfig+4−41
@@ -1,10 +1,6 @@
1menu "Distributed Switch Architecture drivers"1menu "Distributed Switch Architecture drivers"
2 depends on HAVE_NET_DSA2 depends on HAVE_NET_DSA
3 3
4config NET_DSA_MV88E6XXX
5 tristate
6 default n
7
8config NET_DSA_MV88E60604config NET_DSA_MV88E6060
9 tristate "Marvell 88E6060 ethernet switch chip support"5 tristate "Marvell 88E6060 ethernet switch chip support"
10 depends on NET_DSA6 depends on NET_DSA
@@ -13,46 +9,13 @@ config NET_DSA_MV88E6060 · 2 unmodified lines
13 This enables support for the Marvell 88E6060 ethernet switch9 This enables support for the Marvell 88E6060 ethernet switch
14 chip.10 chip.
15 11
16config NET_DSA_MV88E6XXX_NEED_PPU12config NET_DSA_MV88E6XXX
17 bool13 tristate "Marvell 88E6xxx Ethernet switch chip support"
18 default n
19
20config 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
30config 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
39config 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
48config NET_DSA_MV88E6352
49 tristate "Marvell 88E6172/6176/6320/6321/6352 ethernet switch chip support"
50 depends on NET_DSA14 depends on NET_DSA
51 select NET_DSA_MV88E6XXX
52 select NET_DSA_TAG_EDSA15 select NET_DSA_TAG_EDSA
53 ---help---16 ---help---
54 This enables support for the Marvell 88E6172, 88E6176, 88E6320,17 This enables support for most of the Marvell 88E6xxx models of
55 88E6321 and 88E6352 ethernet switch chips.18 Ethernet switch chips, except 88E6060.
56 19
57config NET_DSA_BCM_SF220config NET_DSA_BCM_SF2
58 tristate "Broadcom Starfighter 2 Ethernet switch support"21 tristate "Broadcom Starfighter 2 Ethernet switch support"
drivers/net/dsa/Makefile+1−14
@@ -1,16 +1,3 @@
1obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o1obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o
2obj-$(CONFIG_NET_DSA_MV88E6XXX) += mv88e6xxx_drv.o2obj-$(CONFIG_NET_DSA_MV88E6XXX) += mv88e6xxx.o
3mv88e6xxx_drv-y += mv88e6xxx.o
4ifdef CONFIG_NET_DSA_MV88E6123
5mv88e6xxx_drv-y += mv88e6123.o
6endif
7ifdef CONFIG_NET_DSA_MV88E6131
8mv88e6xxx_drv-y += mv88e6131.o
9endif
10ifdef CONFIG_NET_DSA_MV88E6352
11mv88e6xxx_drv-y += mv88e6352.o
12endif
13ifdef CONFIG_NET_DSA_MV88E6171
14mv88e6xxx_drv-y += mv88e6171.o
15endif
16obj-$(CONFIG_NET_DSA_BCM_SF2) += bcm_sf2.o3obj-$(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
20static 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
42static 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
51static 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
88static 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
110struct 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
128MODULE_ALIAS("platform:mv88e6123");
129MODULE_ALIAS("platform:mv88e6161");
130MODULE_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
20static 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
48static 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
57static 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
120static 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
144static 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
154static int
155mv88e6131_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
165static int
166mv88e6131_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
177struct 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
201MODULE_ALIAS("platform:mv88e6085");
202MODULE_ALIAS("platform:mv88e6095");
203MODULE_ALIAS("platform:mv88e6095f");
204MODULE_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
20static 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
48static 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
57static 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
96static 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
118struct 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
148MODULE_ALIAS("platform:mv88e6171");
149MODULE_ALIAS("platform:mv88e6175");
150MODULE_ALIAS("platform:mv88e6350");
151MODULE_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
25static 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
65static 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
74static 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
111static 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
135static 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);
153error:
154 mutex_unlock(&ps->eeprom_mutex);
155 return ret;
156}
157
158static 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
221static 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
236static 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);
255error:
256 mutex_unlock(&ps->eeprom_mutex);
257 return ret;
258}
259
260static 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
336struct 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
373MODULE_ALIAS("platform:mv88e6172");
374MODULE_ALIAS("platform:mv88e6176");
375MODULE_ALIAS("platform:mv88e6320");
376MODULE_ALIAS("platform:mv88e6321");
377MODULE_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
173 return ret;173 return ret;
174}174}
175 175
176int mv88e6xxx_set_addr_direct(struct dsa_switch *ds, u8 *addr)176static int mv88e6xxx_set_addr_direct(struct dsa_switch *ds, u8 *addr)
177{177{
178 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);178 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
179 int err;179 int err;
@@ -192,7 +192,7 @@ int mv88e6xxx_set_addr_direct(struct dsa_switch *ds, u8 *addr) · 12 unmodified lines
192 (addr[4] << 8) | addr[5]);192 (addr[4] << 8) | addr[5]);
193}193}
194 194
195int mv88e6xxx_set_addr_indirect(struct dsa_switch *ds, u8 *addr)195static int mv88e6xxx_set_addr_indirect(struct dsa_switch *ds, u8 *addr)
196{196{
197 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);197 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
198 int ret;198 int ret;
@@ -225,6 +225,16 @@ int mv88e6xxx_set_addr_indirect(struct dsa_switch *ds, u8 *addr) · 26 unmodified lines
225 return 0;225 return 0;
226}226}
227 227
228int 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
228static int _mv88e6xxx_phy_read(struct mv88e6xxx_priv_state *ps, int addr,238static int _mv88e6xxx_phy_read(struct mv88e6xxx_priv_state *ps, int addr,
229 int regnum)239 int regnum)
230{240{
@@ -241,24 +251,23 @@ static int _mv88e6xxx_phy_write(struct mv88e6xxx_priv_state *ps, int addr, · 10 unmodified lines
241 return 0;251 return 0;
242}252}
243 253
244#ifdef CONFIG_NET_DSA_MV88E6XXX_NEED_PPU
245static int mv88e6xxx_ppu_disable(struct mv88e6xxx_priv_state *ps)254static int mv88e6xxx_ppu_disable(struct mv88e6xxx_priv_state *ps)
246{255{
247 int ret;256 int ret;
248 unsigned long timeout;257 unsigned long timeout;
249 258
250 ret = mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_CONTROL);259 ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_CONTROL);
251 if (ret < 0)260 if (ret < 0)
252 return ret;261 return ret;
253 262
254 ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL,263 ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL,
255 ret & ~GLOBAL_CONTROL_PPU_ENABLE);264 ret & ~GLOBAL_CONTROL_PPU_ENABLE);
256 if (ret)265 if (ret)
257 return ret;266 return ret;
258 267
259 timeout = jiffies + 1 * HZ;268 timeout = jiffies + 1 * HZ;
260 while (time_before(jiffies, timeout)) {269 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);
262 if (ret < 0)271 if (ret < 0)
263 return ret;272 return ret;
264 273
@@ -361,35 +370,33 @@ void mv88e6xxx_ppu_state_init(struct mv88e6xxx_priv_state *ps) · 96 unmodified lines
361 ps->ppu_timer.function = mv88e6xxx_ppu_reenable_timer;370 ps->ppu_timer.function = mv88e6xxx_ppu_reenable_timer;
362}371}
363 372
364int mv88e6xxx_phy_read_ppu(struct dsa_switch *ds, int addr, int regnum)373static int mv88e6xxx_phy_read_ppu(struct mv88e6xxx_priv_state *ps, int addr,
374 int regnum)
365{375{
366 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
367 int ret;376 int ret;
368 377
369 ret = mv88e6xxx_ppu_access_get(ps);378 ret = mv88e6xxx_ppu_access_get(ps);
370 if (ret >= 0) {379 if (ret >= 0) {
371 ret = mv88e6xxx_reg_read(ps, addr, regnum);380 ret = _mv88e6xxx_reg_read(ps, addr, regnum);
372 mv88e6xxx_ppu_access_put(ps);381 mv88e6xxx_ppu_access_put(ps);
373 }382 }
374 383
375 return ret;384 return ret;
376}385}
377 386
378int mv88e6xxx_phy_write_ppu(struct dsa_switch *ds, int addr,387static int mv88e6xxx_phy_write_ppu(struct mv88e6xxx_priv_state *ps, int addr,
379 int regnum, u16 val)388 int regnum, u16 val)
380{389{
381 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
382 int ret;390 int ret;
383 391
384 ret = mv88e6xxx_ppu_access_get(ps);392 ret = mv88e6xxx_ppu_access_get(ps);
385 if (ret >= 0) {393 if (ret >= 0) {
386 ret = mv88e6xxx_reg_write(ps, addr, regnum, val);394 ret = _mv88e6xxx_reg_write(ps, addr, regnum, val);
387 mv88e6xxx_ppu_access_put(ps);395 mv88e6xxx_ppu_access_put(ps);
388 }396 }
389 397
390 return ret;398 return ret;
391}399}
392#endif
393 400
394static bool mv88e6xxx_6065_family(struct mv88e6xxx_priv_state *ps)401static bool mv88e6xxx_6065_family(struct mv88e6xxx_priv_state *ps)
395{402{
@@ -460,8 +467,8 @@ static bool mv88e6xxx_has_stu(struct mv88e6xxx_priv_state *ps) · 64 unmodified lines
460 * phy. However, in the case of a fixed link phy, we force the port467 * phy. However, in the case of a fixed link phy, we force the port
461 * settings from the fixed link settings.468 * settings from the fixed link settings.
462 */469 */
463void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port,470static void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port,
464 struct phy_device *phydev)471 struct phy_device *phydev)
465{472{
466 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);473 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
467 u32 reg;474 u32 reg;
@@ -707,7 +714,8 @@ static uint64_t _mv88e6xxx_get_ethtool_stat(struct mv88e6xxx_priv_state *ps, · 239 unmodified lines
707 return value;714 return value;
708}715}
709 716
710void mv88e6xxx_get_strings(struct dsa_switch *ds, int port, uint8_t *data)717static void mv88e6xxx_get_strings(struct dsa_switch *ds, int port,
718 uint8_t *data)
711{719{
712 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);720 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
713 struct mv88e6xxx_hw_stat *stat;721 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
723 }731 }
724}732}
725 733
726int mv88e6xxx_get_sset_count(struct dsa_switch *ds)734static int mv88e6xxx_get_sset_count(struct dsa_switch *ds)
727{735{
728 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);736 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
729 struct mv88e6xxx_hw_stat *stat;737 struct mv88e6xxx_hw_stat *stat;
@@ -737,9 +745,8 @@ int mv88e6xxx_get_sset_count(struct dsa_switch *ds) · 7 unmodified lines
737 return j;745 return j;
738}746}
739 747
740void748static void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, int port,
741mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds,749 uint64_t *data)
742 int port, uint64_t *data)
743{750{
744 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);751 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
745 struct mv88e6xxx_hw_stat *stat;752 struct mv88e6xxx_hw_stat *stat;
@@ -764,13 +771,13 @@ mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, · 18 unmodified lines
764 mutex_unlock(&ps->smi_mutex);771 mutex_unlock(&ps->smi_mutex);
765}772}
766 773
767int mv88e6xxx_get_regs_len(struct dsa_switch *ds, int port)774static int mv88e6xxx_get_regs_len(struct dsa_switch *ds, int port)
768{775{
769 return 32 * sizeof(u16);776 return 32 * sizeof(u16);
770}777}
771 778
772void mv88e6xxx_get_regs(struct dsa_switch *ds, int port,779static void mv88e6xxx_get_regs(struct dsa_switch *ds, int port,
773 struct ethtool_regs *regs, void *_p)780 struct ethtool_regs *regs, void *_p)
774{781{
775 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);782 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
776 u16 *p = _p;783 u16 *p = _p;
@@ -780,13 +787,17 @@ void mv88e6xxx_get_regs(struct dsa_switch *ds, int port, · 3 unmodified lines
780 787
781 memset(p, 0xff, 32 * sizeof(u16));788 memset(p, 0xff, 32 * sizeof(u16));
782 789
790 mutex_lock(&ps->smi_mutex);
791
783 for (i = 0; i < 32; i++) {792 for (i = 0; i < 32; i++) {
784 int ret;793 int ret;
785 794
786 ret = mv88e6xxx_reg_read(ps, REG_PORT(port), i);795 ret = _mv88e6xxx_reg_read(ps, REG_PORT(port), i);
787 if (ret >= 0)796 if (ret >= 0)
788 p[i] = ret;797 p[i] = ret;
789 }798 }
799
800 mutex_unlock(&ps->smi_mutex);
790}801}
791 802
792static int _mv88e6xxx_wait(struct mv88e6xxx_priv_state *ps, int reg, int offset,803static 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
826 GLOBAL2_SMI_OP_BUSY);837 GLOBAL2_SMI_OP_BUSY);
827}838}
828 839
829int mv88e6xxx_eeprom_load_wait(struct dsa_switch *ds)840static int mv88e6xxx_eeprom_load_wait(struct dsa_switch *ds)
830{841{
831 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);842 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
832 843
@@ -834,7 +845,7 @@ int mv88e6xxx_eeprom_load_wait(struct dsa_switch *ds) · 1 unmodified line
834 GLOBAL2_EEPROM_OP_LOAD);845 GLOBAL2_EEPROM_OP_LOAD);
835}846}
836 847
837int mv88e6xxx_eeprom_busy_wait(struct dsa_switch *ds)848static int mv88e6xxx_eeprom_busy_wait(struct dsa_switch *ds)
838{849{
839 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);850 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
840 851
@@ -842,6 +853,215 @@ int mv88e6xxx_eeprom_busy_wait(struct dsa_switch *ds) · 1 unmodified line
842 GLOBAL2_EEPROM_OP_BUSY);853 GLOBAL2_EEPROM_OP_BUSY);
843}854}
844 855
856static 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);
874error:
875 mutex_unlock(&ps->eeprom_mutex);
876 return ret;
877}
878
879static 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
946static 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
961static 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);
980error:
981 mutex_unlock(&ps->eeprom_mutex);
982 return ret;
983}
984
985static 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
845static int _mv88e6xxx_atu_wait(struct mv88e6xxx_priv_state *ps)1065static int _mv88e6xxx_atu_wait(struct mv88e6xxx_priv_state *ps)
846{1066{
847 return _mv88e6xxx_wait(ps, REG_GLOBAL, GLOBAL_ATU_OP,1067 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
884 return _mv88e6xxx_phy_wait(ps);1104 return _mv88e6xxx_phy_wait(ps);
885}1105}
886 1106
887int mv88e6xxx_get_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e)1107static int mv88e6xxx_get_eee(struct dsa_switch *ds, int port,
1108 struct ethtool_eee *e)
888{1109{
889 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);1110 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
890 int reg;1111 int reg;
891 1112
1113 if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_EEE))
1114 return -EOPNOTSUPP;
1115
892 mutex_lock(&ps->smi_mutex);1116 mutex_lock(&ps->smi_mutex);
893 1117
894 reg = _mv88e6xxx_phy_read_indirect(ps, port, 16);1118 reg = _mv88e6xxx_phy_read_indirect(ps, port, 16);
@@ -910,13 +1134,16 @@ out: · 15 unmodified lines
910 return reg;1134 return reg;
911}1135}
912 1136
913int mv88e6xxx_set_eee(struct dsa_switch *ds, int port,1137static int mv88e6xxx_set_eee(struct dsa_switch *ds, int port,
914 struct phy_device *phydev, struct ethtool_eee *e)1138 struct phy_device *phydev, struct ethtool_eee *e)
915{1139{
916 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);1140 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
917 int reg;1141 int reg;
918 int ret;1142 int ret;
919 1143
1144 if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_EEE))
1145 return -EOPNOTSUPP;
1146
920 mutex_lock(&ps->smi_mutex);1147 mutex_lock(&ps->smi_mutex);
921 1148
922 ret = _mv88e6xxx_phy_read_indirect(ps, port, 16);1149 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
1138 return _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_BASE_VLAN, reg);1365 return _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_BASE_VLAN, reg);
1139}1366}
1140 1367
1141void mv88e6xxx_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)1368static void mv88e6xxx_port_stp_state_set(struct dsa_switch *ds, int port,
1369 u8 state)
1142{1370{
1143 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);1371 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
1144 int stp_state;1372 int stp_state;
1145 1373
1374 if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_PORTSTATE))
1375 return;
1376
1146 switch (state) {1377 switch (state) {
1147 case BR_STATE_DISABLED:1378 case BR_STATE_DISABLED:
1148 stp_state = PORT_CONTROL_STATE_DISABLED;1379 stp_state = PORT_CONTROL_STATE_DISABLED;
@@ -1358,15 +1589,18 @@ static int _mv88e6xxx_vtu_getnext(struct mv88e6xxx_priv_state *ps, · 209 unmodified lines
1358 return 0;1589 return 0;
1359}1590}
1360 1591
1361int mv88e6xxx_port_vlan_dump(struct dsa_switch *ds, int port,1592static int mv88e6xxx_port_vlan_dump(struct dsa_switch *ds, int port,
1362 struct switchdev_obj_port_vlan *vlan,1593 struct switchdev_obj_port_vlan *vlan,
1363 int (*cb)(struct switchdev_obj *obj))1594 int (*cb)(struct switchdev_obj *obj))
1364{1595{
1365 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);1596 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
1366 struct mv88e6xxx_vtu_stu_entry next;1597 struct mv88e6xxx_vtu_stu_entry next;
1367 u16 pvid;1598 u16 pvid;
1368 int err;1599 int err;
1369 1600
1601 if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_VTU))
1602 return -EOPNOTSUPP;
1603
1370 mutex_lock(&ps->smi_mutex);1604 mutex_lock(&ps->smi_mutex);
1371 1605
1372 err = _mv88e6xxx_port_pvid_get(ps, port, &pvid);1606 err = _mv88e6xxx_port_pvid_get(ps, port, &pvid);
@@ -1782,14 +2016,17 @@ static const char * const mv88e6xxx_port_8021q_mode_names[] = { · 409 unmodified lines
1782 [PORT_CONTROL_2_8021Q_SECURE] = "Secure",2016 [PORT_CONTROL_2_8021Q_SECURE] = "Secure",
1783};2017};
1784 2018
1785int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port,2019static int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port,
1786 bool vlan_filtering)2020 bool vlan_filtering)
1787{2021{
1788 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);2022 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
1789 u16 old, new = vlan_filtering ? PORT_CONTROL_2_8021Q_SECURE :2023 u16 old, new = vlan_filtering ? PORT_CONTROL_2_8021Q_SECURE :
1790 PORT_CONTROL_2_8021Q_DISABLED;2024 PORT_CONTROL_2_8021Q_DISABLED;
1791 int ret;2025 int ret;
1792 2026
2027 if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_VTU))
2028 return -EOPNOTSUPP;
2029
1793 mutex_lock(&ps->smi_mutex);2030 mutex_lock(&ps->smi_mutex);
1794 2031
1795 ret = _mv88e6xxx_reg_read(ps, REG_PORT(port), PORT_CONTROL_2);2032 ret = _mv88e6xxx_reg_read(ps, REG_PORT(port), PORT_CONTROL_2);
@@ -1819,12 +2056,16 @@ unlock: · 23 unmodified lines
1819 return ret;2056 return ret;
1820}2057}
1821 2058
1822int mv88e6xxx_port_vlan_prepare(struct dsa_switch *ds, int port,2059static int mv88e6xxx_port_vlan_prepare(struct dsa_switch *ds, int port,
1823 const struct switchdev_obj_port_vlan *vlan,2060 const struct switchdev_obj_port_vlan *vlan,
1824 struct switchdev_trans *trans)2061 struct switchdev_trans *trans)
1825{2062{
2063 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
1826 int err;2064 int err;
1827 2065
2066 if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_VTU))
2067 return -EOPNOTSUPP;
2068
1828 /* If the requested port doesn't belong to the same bridge as the VLAN2069 /* If the requested port doesn't belong to the same bridge as the VLAN
1829 * members, do not support it (yet) and fallback to software VLAN.2070 * members, do not support it (yet) and fallback to software VLAN.
1830 */2071 */
@@ -1856,15 +2097,18 @@ static int _mv88e6xxx_port_vlan_add(struct mv88e6xxx_priv_state *ps, int port, · 25 unmodified lines
1856 return _mv88e6xxx_vtu_loadpurge(ps, &vlan);2097 return _mv88e6xxx_vtu_loadpurge(ps, &vlan);
1857}2098}
1858 2099
1859void mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port,2100static void mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port,
1860 const struct switchdev_obj_port_vlan *vlan,2101 const struct switchdev_obj_port_vlan *vlan,
1861 struct switchdev_trans *trans)2102 struct switchdev_trans *trans)
1862{2103{
1863 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);2104 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
1864 bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;2105 bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
1865 bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;2106 bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
1866 u16 vid;2107 u16 vid;
1867 2108
2109 if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_VTU))
2110 return;
2111
1868 mutex_lock(&ps->smi_mutex);2112 mutex_lock(&ps->smi_mutex);
1869 2113
1870 for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid)2114 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
1915 return _mv88e6xxx_atu_remove(ps, vlan.fid, port, false);2159 return _mv88e6xxx_atu_remove(ps, vlan.fid, port, false);
1916}2160}
1917 2161
1918int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port,2162static int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port,
1919 const struct switchdev_obj_port_vlan *vlan)2163 const struct switchdev_obj_port_vlan *vlan)
1920{2164{
1921 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);2165 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
1922 u16 pvid, vid;2166 u16 pvid, vid;
1923 int err = 0;2167 int err = 0;
1924 2168
2169 if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_VTU))
2170 return -EOPNOTSUPP;
2171
1925 mutex_lock(&ps->smi_mutex);2172 mutex_lock(&ps->smi_mutex);
1926 2173
1927 err = _mv88e6xxx_port_pvid_get(ps, port, &pvid);2174 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
2026 return _mv88e6xxx_atu_load(ps, &entry);2273 return _mv88e6xxx_atu_load(ps, &entry);
2027}2274}
2028 2275
2029int mv88e6xxx_port_fdb_prepare(struct dsa_switch *ds, int port,2276static int mv88e6xxx_port_fdb_prepare(struct dsa_switch *ds, int port,
2030 const struct switchdev_obj_port_fdb *fdb,2277 const struct switchdev_obj_port_fdb *fdb,
2031 struct switchdev_trans *trans)2278 struct switchdev_trans *trans)
2032{2279{
2280 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
2281
2282 if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_ATU))
2283 return -EOPNOTSUPP;
2284
2033 /* We don't need any dynamic resource from the kernel (yet),2285 /* We don't need any dynamic resource from the kernel (yet),
2034 * so skip the prepare phase.2286 * so skip the prepare phase.
2035 */2287 */
2036 return 0;2288 return 0;
2037}2289}
2038 2290
2039void mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port,2291static void mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port,
2040 const struct switchdev_obj_port_fdb *fdb,2292 const struct switchdev_obj_port_fdb *fdb,
2041 struct switchdev_trans *trans)2293 struct switchdev_trans *trans)
2042{2294{
2043 int state = is_multicast_ether_addr(fdb->addr) ?2295 int state = is_multicast_ether_addr(fdb->addr) ?
2044 GLOBAL_ATU_DATA_STATE_MC_STATIC :2296 GLOBAL_ATU_DATA_STATE_MC_STATIC :
2045 GLOBAL_ATU_DATA_STATE_UC_STATIC;2297 GLOBAL_ATU_DATA_STATE_UC_STATIC;
2046 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);2298 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
2047 2299
2300 if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_ATU))
2301 return;
2302
2048 mutex_lock(&ps->smi_mutex);2303 mutex_lock(&ps->smi_mutex);
2049 if (_mv88e6xxx_port_fdb_load(ps, port, fdb->addr, fdb->vid, state))2304 if (_mv88e6xxx_port_fdb_load(ps, port, fdb->addr, fdb->vid, state))
2050 netdev_err(ds->ports[port], "failed to load MAC address\n");2305 netdev_err(ds->ports[port], "failed to load MAC address\n");
2051 mutex_unlock(&ps->smi_mutex);2306 mutex_unlock(&ps->smi_mutex);
2052}2307}
2053 2308
2054int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port,2309static int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port,
2055 const struct switchdev_obj_port_fdb *fdb)2310 const struct switchdev_obj_port_fdb *fdb)
2056{2311{
2057 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);2312 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
2058 int ret;2313 int ret;
2059 2314
2315 if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_ATU))
2316 return -EOPNOTSUPP;
2317
2060 mutex_lock(&ps->smi_mutex);2318 mutex_lock(&ps->smi_mutex);
2061 ret = _mv88e6xxx_port_fdb_load(ps, port, fdb->addr, fdb->vid,2319 ret = _mv88e6xxx_port_fdb_load(ps, port, fdb->addr, fdb->vid,
2062 GLOBAL_ATU_DATA_STATE_UNUSED);2320 GLOBAL_ATU_DATA_STATE_UNUSED);
@@ -2151,9 +2409,9 @@ static int _mv88e6xxx_port_fdb_dump_one(struct mv88e6xxx_priv_state *ps, · 88 unmodified lines
2151 return err;2409 return err;
2152}2410}
2153 2411
2154int mv88e6xxx_port_fdb_dump(struct dsa_switch *ds, int port,2412static int mv88e6xxx_port_fdb_dump(struct dsa_switch *ds, int port,
2155 struct switchdev_obj_port_fdb *fdb,2413 struct switchdev_obj_port_fdb *fdb,
2156 int (*cb)(struct switchdev_obj *obj))2414 int (*cb)(struct switchdev_obj *obj))
2157{2415{
2158 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);2416 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
2159 struct mv88e6xxx_vtu_stu_entry vlan = {2417 struct mv88e6xxx_vtu_stu_entry vlan = {
@@ -2162,6 +2420,9 @@ int mv88e6xxx_port_fdb_dump(struct dsa_switch *ds, int port, · 2 unmodified lines
2162 u16 fid;2420 u16 fid;
2163 int err;2421 int err;
2164 2422
2423 if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_ATU))
2424 return -EOPNOTSUPP;
2425
2165 mutex_lock(&ps->smi_mutex);2426 mutex_lock(&ps->smi_mutex);
2166 2427
2167 /* Dump port's default Filtering Information Database (VLAN ID 0) */2428 /* Dump port's default Filtering Information Database (VLAN ID 0) */
@@ -2198,12 +2459,15 @@ unlock: · 30 unmodified lines
2198 return err;2459 return err;
2199}2460}
2200 2461
2201int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port,2462static int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port,
2202 struct net_device *bridge)2463 struct net_device *bridge)
2203{2464{
2204 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);2465 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
2205 int i, err = 0;2466 int i, err = 0;
2206 2467
2468 if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_VLANTABLE))
2469 return -EOPNOTSUPP;
2470
2207 mutex_lock(&ps->smi_mutex);2471 mutex_lock(&ps->smi_mutex);
2208 2472
2209 /* Assign the bridge and remap each port's VLANTable */2473 /* 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
2222 return err;2486 return err;
2223}2487}
2224 2488
2225void mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port)2489static void mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port)
2226{2490{
2227 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);2491 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
2228 struct net_device *bridge = ps->ports[port].bridge_dev;2492 struct net_device *bridge = ps->ports[port].bridge_dev;
2229 int i;2493 int i;
2230 2494
2495 if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_VLANTABLE))
2496 return;
2497
2231 mutex_lock(&ps->smi_mutex);2498 mutex_lock(&ps->smi_mutex);
2232 2499
2233 /* Unassign the bridge and remap each port's VLANTable */2500 /* Unassign the bridge and remap each port's VLANTable */
@@ -2294,6 +2561,68 @@ restore_page_0: · 60 unmodified lines
2294 return ret;2561 return ret;
2295}2562}
2296 2563
2564static 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
2297static int mv88e6xxx_power_on_serdes(struct mv88e6xxx_priv_state *ps)2626static int mv88e6xxx_power_on_serdes(struct mv88e6xxx_priv_state *ps)
2298{2627{
2299 int ret;2628 int ret;
@@ -2313,14 +2642,12 @@ static int mv88e6xxx_power_on_serdes(struct mv88e6xxx_priv_state *ps) · 13 unmodified lines
2313 return ret;2642 return ret;
2314}2643}
2315 2644
2316static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)2645static int mv88e6xxx_setup_port(struct mv88e6xxx_priv_state *ps, int port)
2317{2646{
2318 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);2647 struct dsa_switch *ds = ps->ds;
2319 int ret;2648 int ret;
2320 u16 reg;2649 u16 reg;
2321 2650
2322 mutex_lock(&ps->smi_mutex);
2323
2324 if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) ||2651 if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) ||
2325 mv88e6xxx_6165_family(ps) || mv88e6xxx_6097_family(ps) ||2652 mv88e6xxx_6165_family(ps) || mv88e6xxx_6097_family(ps) ||
2326 mv88e6xxx_6185_family(ps) || mv88e6xxx_6095_family(ps) ||2653 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
2349 ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),2676 ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
2350 PORT_PCS_CTRL, reg);2677 PORT_PCS_CTRL, reg);
2351 if (ret)2678 if (ret)
2352 goto abort;2679 return ret;
2353 }2680 }
2354 2681
2355 /* Port Control: disable Drop-on-Unlock, disable Drop-on-Lock,2682 /* 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
2413 ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),2740 ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
2414 PORT_CONTROL, reg);2741 PORT_CONTROL, reg);
2415 if (ret)2742 if (ret)
2416 goto abort;2743 return ret;
2417 }2744 }
2418 2745
2419 /* If this port is connected to a SerDes, make sure the SerDes is not2746 /* 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
2422 if (mv88e6xxx_6352_family(ps)) {2749 if (mv88e6xxx_6352_family(ps)) {
2423 ret = _mv88e6xxx_reg_read(ps, REG_PORT(port), PORT_STATUS);2750 ret = _mv88e6xxx_reg_read(ps, REG_PORT(port), PORT_STATUS);
2424 if (ret < 0)2751 if (ret < 0)
2425 goto abort;2752 return ret;
2426 ret &= PORT_STATUS_CMODE_MASK;2753 ret &= PORT_STATUS_CMODE_MASK;
2427 if ((ret == PORT_STATUS_CMODE_100BASE_X) ||2754 if ((ret == PORT_STATUS_CMODE_100BASE_X) ||
2428 (ret == PORT_STATUS_CMODE_1000BASE_X) ||2755 (ret == PORT_STATUS_CMODE_1000BASE_X) ||
2429 (ret == PORT_STATUS_CMODE_SGMII)) {2756 (ret == PORT_STATUS_CMODE_SGMII)) {
2430 ret = mv88e6xxx_power_on_serdes(ps);2757 ret = mv88e6xxx_power_on_serdes(ps);
2431 if (ret < 0)2758 if (ret < 0)
2432 goto abort;2759 return ret;
2433 }2760 }
2434 }2761 }
2435 2762
@@ -2466,7 +2793,7 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) · 30 unmodified lines
2466 ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),2793 ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
2467 PORT_CONTROL_2, reg);2794 PORT_CONTROL_2, reg);
2468 if (ret)2795 if (ret)
2469 goto abort;2796 return ret;
2470 }2797 }
2471 2798
2472 /* Port Association Vector: when learning source addresses2799 /* 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
2481 2808
2482 ret = _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_ASSOC_VECTOR, reg);2809 ret = _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_ASSOC_VECTOR, reg);
2483 if (ret)2810 if (ret)
2484 goto abort;2811 return ret;
2485 2812
2486 /* Egress rate control 2: disable egress rate control. */2813 /* Egress rate control 2: disable egress rate control. */
2487 ret = _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_RATE_CONTROL_2,2814 ret = _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_RATE_CONTROL_2,
2488 0x0000);2815 0x0000);
2489 if (ret)2816 if (ret)
2490 goto abort;2817 return ret;
2491 2818
2492 if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) ||2819 if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) ||
2493 mv88e6xxx_6165_family(ps) || mv88e6xxx_6097_family(ps) ||2820 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
2499 ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),2826 ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
2500 PORT_PAUSE_CTRL, 0x0000);2827 PORT_PAUSE_CTRL, 0x0000);
2501 if (ret)2828 if (ret)
2502 goto abort;2829 return ret;
2503 2830
2504 /* Port ATU control: disable limiting the number of2831 /* Port ATU control: disable limiting the number of
2505 * address database entries that this port is allowed2832 * 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
2513 ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),2840 ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
2514 PORT_PRI_OVERRIDE, 0x0000);2841 PORT_PRI_OVERRIDE, 0x0000);
2515 if (ret)2842 if (ret)
2516 goto abort;2843 return ret;
2517 2844
2518 /* Port Ethertype: use the Ethertype DSA Ethertype2845 /* Port Ethertype: use the Ethertype DSA Ethertype
2519 * value.2846 * value.
@@ -2521,14 +2848,14 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) · 1 unmodified line
2521 ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),2848 ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
2522 PORT_ETH_TYPE, ETH_P_EDSA);2849 PORT_ETH_TYPE, ETH_P_EDSA);
2523 if (ret)2850 if (ret)
2524 goto abort;2851 return ret;
2525 /* Tag Remap: use an identity 802.1p prio -> switch2852 /* Tag Remap: use an identity 802.1p prio -> switch
2526 * prio mapping.2853 * prio mapping.
2527 */2854 */
2528 ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),2855 ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
2529 PORT_TAG_REGMAP_0123, 0x3210);2856 PORT_TAG_REGMAP_0123, 0x3210);
2530 if (ret)2857 if (ret)
2531 goto abort;2858 return ret;
2532 2859
2533 /* Tag Remap 2: use an identity 802.1p prio -> switch2860 /* Tag Remap 2: use an identity 802.1p prio -> switch
2534 * prio mapping.2861 * prio mapping.
@@ -2536,7 +2863,7 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) · 1 unmodified line
2536 ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),2863 ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
2537 PORT_TAG_REGMAP_4567, 0x7654);2864 PORT_TAG_REGMAP_4567, 0x7654);
2538 if (ret)2865 if (ret)
2539 goto abort;2866 return ret;
2540 }2867 }
2541 2868
2542 if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) ||2869 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
2547 ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),2874 ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
2548 PORT_RATE_CONTROL, 0x0001);2875 PORT_RATE_CONTROL, 0x0001);
2549 if (ret)2876 if (ret)
2550 goto abort;2877 return ret;
2551 }2878 }
2552 2879
2553 /* Port Control 1: disable trunking, disable sending2880 /* 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
2555 */2882 */
2556 ret = _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_CONTROL_1, 0x0000);2883 ret = _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_CONTROL_1, 0x0000);
2557 if (ret)2884 if (ret)
2558 goto abort;2885 return ret;
2559 2886
2560 /* Port based VLAN map: give each port the same default address2887 /* Port based VLAN map: give each port the same default address
2561 * database, and allow bidirectional communication between the2888 * 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
2563 */2890 */
2564 ret = _mv88e6xxx_port_fid_set(ps, port, 0);2891 ret = _mv88e6xxx_port_fid_set(ps, port, 0);
2565 if (ret)2892 if (ret)
2566 goto abort;2893 return ret;
2567 2894
2568 ret = _mv88e6xxx_port_based_vlan_map(ps, port);2895 ret = _mv88e6xxx_port_based_vlan_map(ps, port);
2569 if (ret)2896 if (ret)
2570 goto abort;2897 return ret;
2571 2898
2572 /* Default VLAN ID and priority: don't set a default VLAN2899 /* Default VLAN ID and priority: don't set a default VLAN
2573 * ID, and set the default packet priority to zero.2900 * ID, and set the default packet priority to zero.
2574 */2901 */
2575 ret = _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_DEFAULT_VLAN,2902 ret = _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_DEFAULT_VLAN,
2576 0x0000);2903 0x0000);
2577abort:2904 if (ret)
2578 mutex_unlock(&ps->smi_mutex);2905 return ret;
2579 return ret;
2580}
2581
2582int mv88e6xxx_setup_ports(struct dsa_switch *ds)
2583{
2584 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
2585 int ret;
2586 int i;
2587 2906
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 }
2593 return 0;2907 return 0;
2594}2908}
2595 2909
2596int mv88e6xxx_setup_common(struct mv88e6xxx_priv_state *ps)2910static int mv88e6xxx_setup_global(struct mv88e6xxx_priv_state *ps)
2597{2911{
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;
2599 2917
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;
2601 2925
2602 return 0;2926 err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL, reg);
2603}2927 if (err)
2928 return err;
2604 2929
2605int mv88e6xxx_setup_global(struct dsa_switch *ds)2930 /* Configure the upstream port, and configure it as the port to which
2606{2931 * ingress and egress and ARP monitor frames are to be sent.
2607 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);2932 */
2608 int err;2933 reg = upstream_port << GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT |
2609 int i;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;
2610 2946
2611 mutex_lock(&ps->smi_mutex);
2612 /* Set the default address aging time to 5 minutes, and2947 /* Set the default address aging time to 5 minutes, and
2613 * enable address learn messages to be sent to all message2948 * enable address learn messages to be sent to all message
2614 * ports.2949 * ports.
@@ -2616,45 +2951,45 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds) · 1 unmodified line
2616 err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_ATU_CONTROL,2951 err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_ATU_CONTROL,
2617 0x0140 | GLOBAL_ATU_CONTROL_LEARN2ALL);2952 0x0140 | GLOBAL_ATU_CONTROL_LEARN2ALL);
2618 if (err)2953 if (err)
2619 goto unlock;2954 return err;
2620 2955
2621 /* Configure the IP ToS mapping registers. */2956 /* Configure the IP ToS mapping registers. */
2622 err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_0, 0x0000);2957 err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_0, 0x0000);
2623 if (err)2958 if (err)
2624 goto unlock;2959 return err;
2625 err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_1, 0x0000);2960 err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_1, 0x0000);
2626 if (err)2961 if (err)
2627 goto unlock;2962 return err;
2628 err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_2, 0x5555);2963 err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_2, 0x5555);
2629 if (err)2964 if (err)
2630 goto unlock;2965 return err;
2631 err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_3, 0x5555);2966 err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_3, 0x5555);
2632 if (err)2967 if (err)
2633 goto unlock;2968 return err;
2634 err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_4, 0xaaaa);2969 err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_4, 0xaaaa);
2635 if (err)2970 if (err)
2636 goto unlock;2971 return err;
2637 err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_5, 0xaaaa);2972 err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_5, 0xaaaa);
2638 if (err)2973 if (err)
2639 goto unlock;2974 return err;
2640 err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_6, 0xffff);2975 err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_6, 0xffff);
2641 if (err)2976 if (err)
2642 goto unlock;2977 return err;
2643 err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_7, 0xffff);2978 err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_7, 0xffff);
2644 if (err)2979 if (err)
2645 goto unlock;2980 return err;
2646 2981
2647 /* Configure the IEEE 802.1p priority mapping register. */2982 /* Configure the IEEE 802.1p priority mapping register. */
2648 err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IEEE_PRI, 0xfa41);2983 err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IEEE_PRI, 0xfa41);
2649 if (err)2984 if (err)
2650 goto unlock;2985 return err;
2651 2986
2652 /* Send all frames with destination addresses matching2987 /* Send all frames with destination addresses matching
2653 * 01:80:c2:00:00:0x to the CPU port.2988 * 01:80:c2:00:00:0x to the CPU port.
2654 */2989 */
2655 err = _mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_MGMT_EN_0X, 0xffff);2990 err = _mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_MGMT_EN_0X, 0xffff);
2656 if (err)2991 if (err)
2657 goto unlock;2992 return err;
2658 2993
2659 /* Ignore removed tag data on doubly tagged packets, disable2994 /* Ignore removed tag data on doubly tagged packets, disable
2660 * flow control messages, force flow control priority to the2995 * flow control messages, force flow control priority to the
@@ -2665,15 +3000,15 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds) · 4 unmodified lines
2665 0x7 | GLOBAL2_SWITCH_MGMT_RSVD2CPU | 0x70 |3000 0x7 | GLOBAL2_SWITCH_MGMT_RSVD2CPU | 0x70 |
2666 GLOBAL2_SWITCH_MGMT_FORCE_FLOW_CTRL_PRI);3001 GLOBAL2_SWITCH_MGMT_FORCE_FLOW_CTRL_PRI);
2667 if (err)3002 if (err)
2668 goto unlock;3003 return err;
2669 3004
2670 /* Program the DSA routing table. */3005 /* Program the DSA routing table. */
2671 for (i = 0; i < 32; i++) {3006 for (i = 0; i < 32; i++) {
2672 int nexthop = 0x1f;3007 int nexthop = 0x1f;
2673 3008
2674 if (ds->pd->rtable &&3009 if (ps->ds->pd->rtable &&
2675 i != ds->index && i < ds->dst->pd->nr_chips)3010 i != ps->ds->index && i < ps->ds->dst->pd->nr_chips)
2676 nexthop = ds->pd->rtable[i] & 0x1f;3011 nexthop = ps->ds->pd->rtable[i] & 0x1f;
2677 3012
2678 err = _mv88e6xxx_reg_write(3013 err = _mv88e6xxx_reg_write(
2679 ps, REG_GLOBAL2,3014 ps, REG_GLOBAL2,
@@ -2681,7 +3016,7 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds) · 1 unmodified line
2681 GLOBAL2_DEVICE_MAPPING_UPDATE |3016 GLOBAL2_DEVICE_MAPPING_UPDATE |
2682 (i << GLOBAL2_DEVICE_MAPPING_TARGET_SHIFT) | nexthop);3017 (i << GLOBAL2_DEVICE_MAPPING_TARGET_SHIFT) | nexthop);
2683 if (err)3018 if (err)
2684 goto unlock;3019 return err;
2685 }3020 }
2686 3021
2687 /* Clear all trunk masks. */3022 /* Clear all trunk masks. */
@@ -2691,7 +3026,7 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds) · 3 unmodified lines
2691 (i << GLOBAL2_TRUNK_MASK_NUM_SHIFT) |3026 (i << GLOBAL2_TRUNK_MASK_NUM_SHIFT) |
2692 ((1 << ps->info->num_ports) - 1));3027 ((1 << ps->info->num_ports) - 1));
2693 if (err)3028 if (err)
2694 goto unlock;3029 return err;
2695 }3030 }
2696 3031
2697 /* Clear all trunk mappings. */3032 /* Clear all trunk mappings. */
@@ -2702,7 +3037,7 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds) · 4 unmodified lines
2702 GLOBAL2_TRUNK_MAPPING_UPDATE |3037 GLOBAL2_TRUNK_MAPPING_UPDATE |
2703 (i << GLOBAL2_TRUNK_MAPPING_ID_SHIFT));3038 (i << GLOBAL2_TRUNK_MAPPING_ID_SHIFT));
2704 if (err)3039 if (err)
2705 goto unlock;3040 return err;
2706 }3041 }
2707 3042
2708 if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) ||3043 if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) ||
@@ -2714,7 +3049,7 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds) · 5 unmodified lines
2714 err = _mv88e6xxx_reg_write(ps, REG_GLOBAL2,3049 err = _mv88e6xxx_reg_write(ps, REG_GLOBAL2,
2715 GLOBAL2_MGMT_EN_2X, 0xffff);3050 GLOBAL2_MGMT_EN_2X, 0xffff);
2716 if (err)3051 if (err)
2717 goto unlock;3052 return err;
2718 3053
2719 /* Initialise cross-chip port VLAN table to reset3054 /* Initialise cross-chip port VLAN table to reset
2720 * defaults.3055 * defaults.
@@ -2722,7 +3057,7 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds) · 1 unmodified line
2722 err = _mv88e6xxx_reg_write(ps, REG_GLOBAL2,3057 err = _mv88e6xxx_reg_write(ps, REG_GLOBAL2,
2723 GLOBAL2_PVT_ADDR, 0x9000);3058 GLOBAL2_PVT_ADDR, 0x9000);
2724 if (err)3059 if (err)
2725 goto unlock;3060 return err;
2726 3061
2727 /* Clear the priority override table. */3062 /* Clear the priority override table. */
2728 for (i = 0; i < 16; i++) {3063 for (i = 0; i < 16; i++) {
@@ -2730,7 +3065,7 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds) · 1 unmodified line
2730 GLOBAL2_PRIO_OVERRIDE,3065 GLOBAL2_PRIO_OVERRIDE,
2731 0x8000 | (i << 8));3066 0x8000 | (i << 8));
2732 if (err)3067 if (err)
2733 goto unlock;3068 return err;
2734 }3069 }
2735 }3070 }
2736 3071
@@ -2747,7 +3082,7 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds) · 10 unmodified lines
2747 GLOBAL2_INGRESS_OP,3082 GLOBAL2_INGRESS_OP,
2748 0x9000 | (i << 8));3083 0x9000 | (i << 8));
2749 if (err)3084 if (err)
2750 goto unlock;3085 return err;
2751 }3086 }
2752 }3087 }
2753 3088
@@ -2755,89 +3090,64 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds) · 1 unmodified line
2755 err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_STATS_OP,3090 err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_STATS_OP,
2756 GLOBAL_STATS_OP_FLUSH_ALL);3091 GLOBAL_STATS_OP_FLUSH_ALL);
2757 if (err)3092 if (err)
2758 goto unlock;3093 return err;
2759 3094
2760 /* Wait for the flush to complete. */3095 /* Wait for the flush to complete. */
2761 err = _mv88e6xxx_stats_wait(ps);3096 err = _mv88e6xxx_stats_wait(ps);
2762 if (err < 0)3097 if (err)
2763 goto unlock;3098 return err;
2764 3099
2765 /* Clear all ATU entries */3100 /* Clear all ATU entries */
2766 err = _mv88e6xxx_atu_flush(ps, 0, true);3101 err = _mv88e6xxx_atu_flush(ps, 0, true);
2767 if (err < 0)3102 if (err)
2768 goto unlock;3103 return err;
2769 3104
2770 /* Clear all the VTU and STU entries */3105 /* Clear all the VTU and STU entries */
2771 err = _mv88e6xxx_vtu_stu_flush(ps);3106 err = _mv88e6xxx_vtu_stu_flush(ps);
2772unlock:3107 if (err < 0)
2773 mutex_unlock(&ps->smi_mutex);3108 return err;
2774 3109
2775 return err;3110 return err;
2776}3111}
2777 3112
2778int mv88e6xxx_switch_reset(struct mv88e6xxx_priv_state *ps, bool ppu_active)3113static int mv88e6xxx_setup(struct dsa_switch *ds)
2779{3114{
2780 u16 is_reset = (ppu_active ? 0x8800 : 0xc800);3115 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
2781 struct gpio_desc *gpiod = ps->ds->pd->reset;3116 int err;
2782 unsigned long timeout;
2783 int ret;
2784 int i;3117 int i;
2785 3118
2786 mutex_lock(&ps->smi_mutex);3119 ps->ds = ds;
2787 3120
2788 /* Set all ports to the disabled state. */3121 mutex_init(&ps->smi_mutex);
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;
2793 3122
2794 ret = _mv88e6xxx_reg_write(ps, REG_PORT(i), PORT_CONTROL,3123 INIT_WORK(&ps->bridge_work, mv88e6xxx_bridge_work);
2795 ret & 0xfffc);
2796 if (ret)
2797 goto unlock;
2798 }
2799 3124
2800 /* Wait for transmit queues to drain. */3125 if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_EEPROM))
2801 usleep_range(2000, 4000);3126 mutex_init(&ps->eeprom_mutex);
2802 3127
2803 /* If there is a gpio connected to the reset pin, toggle it */3128 if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_PPU))
2804 if (gpiod) {3129 mv88e6xxx_ppu_state_init(ps);
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 }
2810 3130
2811 /* Reset the switch. Keep the PPU active if requested. The PPU3131 mutex_lock(&ps->smi_mutex);
2812 * needs to be active to support indirect phy register access3132
2813 * through global registers 0x18 and 0x19.3133 err = mv88e6xxx_switch_reset(ps);
2814 */3134 if (err)
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)
2820 goto unlock;3135 goto unlock;
2821 3136
2822 /* Wait up to one second for reset to complete. */3137 err = mv88e6xxx_setup_global(ps);
2823 timeout = jiffies + 1 * HZ;3138 if (err)
2824 while (time_before(jiffies, timeout)) {3139 goto unlock;
2825 ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL, 0x00);
2826 if (ret < 0)
2827 goto unlock;
2828 3140
2829 if ((ret & is_reset) == is_reset)3141 for (i = 0; i < ps->info->num_ports; i++) {
2830 break;3142 err = mv88e6xxx_setup_port(ps, i);
2831 usleep_range(1000, 2000);3143 if (err)
3144 goto unlock;
2832 }3145 }
2833 if (time_after(jiffies, timeout))3146
2834 ret = -ETIMEDOUT;
2835 else
2836 ret = 0;
2837unlock:3147unlock:
2838 mutex_unlock(&ps->smi_mutex);3148 mutex_unlock(&ps->smi_mutex);
2839 3149
2840 return ret;3150 return err;
2841}3151}
2842 3152
2843int mv88e6xxx_phy_page_read(struct dsa_switch *ds, int port, int page, int reg)3153int 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
2873 return -EINVAL;3183 return -EINVAL;
2874}3184}
2875 3185
2876int3186static int mv88e6xxx_phy_read(struct dsa_switch *ds, int port, int regnum)
2877mv88e6xxx_phy_read(struct dsa_switch *ds, int port, int regnum)
2878{3187{
2879 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);3188 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
2880 int addr = mv88e6xxx_port_to_phy_addr(ps, port);3189 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
2884 return 0xffff;3193 return 0xffff;
2885 3194
2886 mutex_lock(&ps->smi_mutex);3195 mutex_lock(&ps->smi_mutex);
2887 ret = _mv88e6xxx_phy_read(ps, addr, regnum);
2888 mutex_unlock(&ps->smi_mutex);
2889 return ret;
2890}
2891
2892int
2893mv88e6xxx_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;
2898 3196
2899 if (addr < 0)3197 if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_PPU))
2900 return 0xffff;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);
2901 3203
2902 mutex_lock(&ps->smi_mutex);
2903 ret = _mv88e6xxx_phy_write(ps, addr, regnum, val);
2904 mutex_unlock(&ps->smi_mutex);3204 mutex_unlock(&ps->smi_mutex);
2905 return ret;3205 return ret;
2906}3206}
2907 3207
2908int3208static int mv88e6xxx_phy_write(struct dsa_switch *ds, int port, int regnum,
2909mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int port, int regnum)3209 u16 val)
2910{3210{
2911 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);3211 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
2912 int addr = mv88e6xxx_port_to_phy_addr(ps, port);3212 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
2916 return 0xffff;3216 return 0xffff;
2917 3217
2918 mutex_lock(&ps->smi_mutex);3218 mutex_lock(&ps->smi_mutex);
2919 ret = _mv88e6xxx_phy_read_indirect(ps, addr, regnum);
2920 mutex_unlock(&ps->smi_mutex);
2921 return ret;
2922}
2923 3219
2924int3220 if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_PPU))
2925mv88e6xxx_phy_write_indirect(struct dsa_switch *ds, int port, int regnum,3221 ret = mv88e6xxx_phy_write_ppu(ps, addr, regnum, val);
2926 u16 val)3222 else if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_SMI_PHY))
2927{3223 ret = _mv88e6xxx_phy_write_indirect(ps, addr, regnum, val);
2928 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);3224 else
2929 int addr = mv88e6xxx_port_to_phy_addr(ps, port);3225 ret = _mv88e6xxx_phy_write(ps, addr, regnum, val);
2930 int ret;
2931
2932 if (addr < 0)
2933 return addr;
2934 3226
2935 mutex_lock(&ps->smi_mutex);
2936 ret = _mv88e6xxx_phy_write_indirect(ps, addr, regnum, val);
2937 mutex_unlock(&ps->smi_mutex);3227 mutex_unlock(&ps->smi_mutex);
2938 return ret;3228 return ret;
2939}3229}
@@ -3002,23 +3292,26 @@ static int mv88e63xx_get_temp(struct dsa_switch *ds, int *temp) · 62 unmodified lines
3002 return 0;3292 return 0;
3003}3293}
3004 3294
3005int mv88e6xxx_get_temp(struct dsa_switch *ds, int *temp)3295static int mv88e6xxx_get_temp(struct dsa_switch *ds, int *temp)
3006{3296{
3007 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);3297 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
3008 3298
3299 if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_TEMP))
3300 return -EOPNOTSUPP;
3301
3009 if (mv88e6xxx_6320_family(ps) || mv88e6xxx_6352_family(ps))3302 if (mv88e6xxx_6320_family(ps) || mv88e6xxx_6352_family(ps))
3010 return mv88e63xx_get_temp(ds, temp);3303 return mv88e63xx_get_temp(ds, temp);
3011 3304
3012 return mv88e61xx_get_temp(ds, temp);3305 return mv88e61xx_get_temp(ds, temp);
3013}3306}
3014 3307
3015int mv88e6xxx_get_temp_limit(struct dsa_switch *ds, int *temp)3308static int mv88e6xxx_get_temp_limit(struct dsa_switch *ds, int *temp)
3016{3309{
3017 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);3310 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
3018 int phy = mv88e6xxx_6320_family(ps) ? 3 : 0;3311 int phy = mv88e6xxx_6320_family(ps) ? 3 : 0;
3019 int ret;3312 int ret;
3020 3313
3021 if (!mv88e6xxx_6320_family(ps) && !mv88e6xxx_6352_family(ps))3314 if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_TEMP_LIMIT))
3022 return -EOPNOTSUPP;3315 return -EOPNOTSUPP;
3023 3316
3024 *temp = 0;3317 *temp = 0;
@@ -3032,13 +3325,13 @@ int mv88e6xxx_get_temp_limit(struct dsa_switch *ds, int *temp) · 7 unmodified lines
3032 return 0;3325 return 0;
3033}3326}
3034 3327
3035int mv88e6xxx_set_temp_limit(struct dsa_switch *ds, int temp)3328static int mv88e6xxx_set_temp_limit(struct dsa_switch *ds, int temp)
3036{3329{
3037 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);3330 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
3038 int phy = mv88e6xxx_6320_family(ps) ? 3 : 0;3331 int phy = mv88e6xxx_6320_family(ps) ? 3 : 0;
3039 int ret;3332 int ret;
3040 3333
3041 if (!mv88e6xxx_6320_family(ps) && !mv88e6xxx_6352_family(ps))3334 if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_TEMP_LIMIT))
3042 return -EOPNOTSUPP;3335 return -EOPNOTSUPP;
3043 3336
3044 ret = mv88e6xxx_phy_page_read(ds, phy, 6, 26);3337 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
3049 (ret & 0xe0ff) | (temp << 8));3342 (ret & 0xe0ff) | (temp << 8));
3050}3343}
3051 3344
3052int mv88e6xxx_get_temp_alarm(struct dsa_switch *ds, bool *alarm)3345static int mv88e6xxx_get_temp_alarm(struct dsa_switch *ds, bool *alarm)
3053{3346{
3054 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);3347 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
3055 int phy = mv88e6xxx_6320_family(ps) ? 3 : 0;3348 int phy = mv88e6xxx_6320_family(ps) ? 3 : 0;
3056 int ret;3349 int ret;
3057 3350
3058 if (!mv88e6xxx_6320_family(ps) && !mv88e6xxx_6352_family(ps))3351 if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_TEMP_LIMIT))
3059 return -EOPNOTSUPP;3352 return -EOPNOTSUPP;
3060 3353
3061 *alarm = false;3354 *alarm = false;
@@ -3070,6 +3363,161 @@ int mv88e6xxx_get_temp_alarm(struct dsa_switch *ds, bool *alarm) · 8 unmodified lines
3070}3363}
3071#endif /* CONFIG_NET_DSA_HWMON */3364#endif /* CONFIG_NET_DSA_HWMON */
3072 3365
3366static 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
3073static const struct mv88e6xxx_info *3521static const struct mv88e6xxx_info *
3074mv88e6xxx_lookup_info(unsigned int prod_num, const struct mv88e6xxx_info *table,3522mv88e6xxx_lookup_info(unsigned int prod_num, const struct mv88e6xxx_info *table,
3075 unsigned int num)3523 unsigned int num)
@@ -3083,10 +3531,9 @@ mv88e6xxx_lookup_info(unsigned int prod_num, const struct mv88e6xxx_info *table, · 7 unmodified lines
3083 return NULL;3531 return NULL;
3084}3532}
3085 3533
3086const char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev,3534static const char *mv88e6xxx_probe(struct device *dsa_dev,
3087 int sw_addr, void **priv,3535 struct device *host_dev, int sw_addr,
3088 const struct mv88e6xxx_info *table,3536 void **priv)
3089 unsigned int num)
3090{3537{
3091 const struct mv88e6xxx_info *info;3538 const struct mv88e6xxx_info *info;
3092 struct mv88e6xxx_priv_state *ps;3539 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
3105 prod_num = (id & 0xfff0) >> 4;3552 prod_num = (id & 0xfff0) >> 4;
3106 rev = id & 0x000f;3553 rev = id & 0x000f;
3107 3554
3108 info = mv88e6xxx_lookup_info(prod_num, table, num);3555 info = mv88e6xxx_lookup_info(prod_num, mv88e6xxx_table,
3556 ARRAY_SIZE(mv88e6xxx_table));
3109 if (!info)3557 if (!info)
3110 return NULL;3558 return NULL;
3111 3559
@@ -3127,41 +3575,73 @@ const char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev, · 15 unmodified lines
3127 return name;3575 return name;
3128}3576}
3129 3577
3578struct 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
3130static int __init mv88e6xxx_init(void)3615static int __init mv88e6xxx_init(void)
3131{3616{
3132#if IS_ENABLED(CONFIG_NET_DSA_MV88E6131)3617 register_switch_driver(&mv88e6xxx_switch_driver);
3133 register_switch_driver(&mv88e6131_switch_driver);3618
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
3144 return 0;3619 return 0;
3145}3620}
3146module_init(mv88e6xxx_init);3621module_init(mv88e6xxx_init);
3147 3622
3148static void __exit mv88e6xxx_cleanup(void)3623static void __exit mv88e6xxx_cleanup(void)
3149{3624{
3150#if IS_ENABLED(CONFIG_NET_DSA_MV88E6171)3625 unregister_switch_driver(&mv88e6xxx_switch_driver);
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
3162}3626}
3163module_exit(mv88e6xxx_cleanup);3627module_exit(mv88e6xxx_cleanup);
3164 3628
3629MODULE_ALIAS("platform:mv88e6085");
3630MODULE_ALIAS("platform:mv88e6095");
3631MODULE_ALIAS("platform:mv88e6095f");
3632MODULE_ALIAS("platform:mv88e6123");
3633MODULE_ALIAS("platform:mv88e6131");
3634MODULE_ALIAS("platform:mv88e6161");
3635MODULE_ALIAS("platform:mv88e6165");
3636MODULE_ALIAS("platform:mv88e6171");
3637MODULE_ALIAS("platform:mv88e6172");
3638MODULE_ALIAS("platform:mv88e6175");
3639MODULE_ALIAS("platform:mv88e6176");
3640MODULE_ALIAS("platform:mv88e6320");
3641MODULE_ALIAS("platform:mv88e6321");
3642MODULE_ALIAS("platform:mv88e6350");
3643MODULE_ALIAS("platform:mv88e6351");
3644MODULE_ALIAS("platform:mv88e6352");
3165MODULE_AUTHOR("Lennert Buytenhek <buytenh@wantstofly.org>");3645MODULE_AUTHOR("Lennert Buytenhek <buytenh@wantstofly.org>");
3166MODULE_DESCRIPTION("Driver for Marvell 88E6XXX ethernet switch chips");3646MODULE_DESCRIPTION("Driver for Marvell 88E6XXX ethernet switch chips");
3167MODULE_LICENSE("GPL");3647MODULE_LICENSE("GPL");
drivers/net/dsa/mv88e6xxx.h+156−83
@@ -338,6 +338,27 @@ · 337 unmodified lines
338 338
339#define MV88E6XXX_N_FID 4096339#define MV88E6XXX_N_FID 4096
340 340
341/* List of supported models */
342enum 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
341enum mv88e6xxx_family {362enum mv88e6xxx_family {
342 MV88E6XXX_FAMILY_NONE,363 MV88E6XXX_FAMILY_NONE,
343 MV88E6XXX_FAMILY_6065, /* 6031 6035 6061 6065 */364 MV88E6XXX_FAMILY_6065, /* 6031 6035 6061 6065 */
@@ -350,12 +371,142 @@ enum mv88e6xxx_family { · 6 unmodified lines
350 MV88E6XXX_FAMILY_6352, /* 6172 6176 6240 6352 */371 MV88E6XXX_FAMILY_6352, /* 6172 6176 6240 6352 */
351};372};
352 373
374enum 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
353struct mv88e6xxx_info {503struct mv88e6xxx_info {
354 enum mv88e6xxx_family family;504 enum mv88e6xxx_family family;
355 u16 prod_num;505 u16 prod_num;
356 const char *name;506 const char *name;
357 unsigned int num_databases;507 unsigned int num_databases;
358 unsigned int num_ports;508 unsigned int num_ports;
509 unsigned long flags;
359};510};
360 511
361struct mv88e6xxx_atu_entry {512struct mv88e6xxx_atu_entry {
@@ -403,7 +554,6 @@ struct mv88e6xxx_priv_state { · 41 unmodified lines
403 struct mii_bus *bus;554 struct mii_bus *bus;
404 int sw_addr;555 int sw_addr;
405 556
406#ifdef CONFIG_NET_DSA_MV88E6XXX_NEED_PPU
407 /* Handles automatic disabling and re-enabling of the PHY557 /* Handles automatic disabling and re-enabling of the PHY
408 * polling unit.558 * polling unit.
409 */559 */
@@ -411,7 +561,6 @@ struct mv88e6xxx_priv_state { · 1 unmodified line
411 int ppu_disabled;561 int ppu_disabled;
412 struct work_struct ppu_work;562 struct work_struct ppu_work;
413 struct timer_list ppu_timer;563 struct timer_list ppu_timer;
414#endif
415 564
416 /* This mutex serialises access to the statistics unit.565 /* This mutex serialises access to the statistics unit.
417 * Hold this mutex over snapshot + dump sequences.566 * Hold this mutex over snapshot + dump sequences.
@@ -449,86 +598,10 @@ struct mv88e6xxx_hw_stat { · 31 unmodified lines
449 enum stat_type type;598 enum stat_type type;
450};599};
451 600
452int mv88e6xxx_switch_reset(struct mv88e6xxx_priv_state *ps, bool ppu_active);601static inline bool mv88e6xxx_has(struct mv88e6xxx_priv_state *ps,
453const char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev,602 unsigned long flags)
454 int sw_addr, void **priv,603{
455 const struct mv88e6xxx_info *table,604 return (ps->info->flags & flags) == flags;
456 unsigned int num);605}
457
458int mv88e6xxx_setup_ports(struct dsa_switch *ds);
459int mv88e6xxx_setup_common(struct mv88e6xxx_priv_state *ps);
460int mv88e6xxx_setup_global(struct dsa_switch *ds);
461int mv88e6xxx_reg_read(struct mv88e6xxx_priv_state *ps, int addr, int reg);
462int mv88e6xxx_reg_write(struct mv88e6xxx_priv_state *ps, int addr,
463 int reg, u16 val);
464int mv88e6xxx_set_addr_direct(struct dsa_switch *ds, u8 *addr);
465int mv88e6xxx_set_addr_indirect(struct dsa_switch *ds, u8 *addr);
466int mv88e6xxx_phy_read(struct dsa_switch *ds, int port, int regnum);
467int mv88e6xxx_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val);
468int mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int port, int regnum);
469int mv88e6xxx_phy_write_indirect(struct dsa_switch *ds, int port, int regnum,
470 u16 val);
471void mv88e6xxx_ppu_state_init(struct mv88e6xxx_priv_state *ps);
472int mv88e6xxx_phy_read_ppu(struct dsa_switch *ds, int addr, int regnum);
473int mv88e6xxx_phy_write_ppu(struct dsa_switch *ds, int addr,
474 int regnum, u16 val);
475void mv88e6xxx_get_strings(struct dsa_switch *ds, int port, uint8_t *data);
476void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, int port,
477 uint64_t *data);
478int mv88e6xxx_get_sset_count(struct dsa_switch *ds);
479int mv88e6xxx_get_sset_count_basic(struct dsa_switch *ds);
480void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port,
481 struct phy_device *phydev);
482int mv88e6xxx_get_regs_len(struct dsa_switch *ds, int port);
483void mv88e6xxx_get_regs(struct dsa_switch *ds, int port,
484 struct ethtool_regs *regs, void *_p);
485int mv88e6xxx_get_temp(struct dsa_switch *ds, int *temp);
486int mv88e6xxx_get_temp_limit(struct dsa_switch *ds, int *temp);
487int mv88e6xxx_set_temp_limit(struct dsa_switch *ds, int temp);
488int mv88e6xxx_get_temp_alarm(struct dsa_switch *ds, bool *alarm);
489int mv88e6xxx_eeprom_load_wait(struct dsa_switch *ds);
490int mv88e6xxx_eeprom_busy_wait(struct dsa_switch *ds);
491int mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int addr, int regnum);
492int mv88e6xxx_phy_write_indirect(struct dsa_switch *ds, int addr, int regnum,
493 u16 val);
494int mv88e6xxx_get_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e);
495int mv88e6xxx_set_eee(struct dsa_switch *ds, int port,
496 struct phy_device *phydev, struct ethtool_eee *e);
497int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port,
498 struct net_device *bridge);
499void mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port);
500void mv88e6xxx_port_stp_state_set(struct dsa_switch *ds, int port, u8 state);
501int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port,
502 bool vlan_filtering);
503int mv88e6xxx_port_vlan_prepare(struct dsa_switch *ds, int port,
504 const struct switchdev_obj_port_vlan *vlan,
505 struct switchdev_trans *trans);
506void mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port,
507 const struct switchdev_obj_port_vlan *vlan,
508 struct switchdev_trans *trans);
509int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port,
510 const struct switchdev_obj_port_vlan *vlan);
511int mv88e6xxx_port_vlan_dump(struct dsa_switch *ds, int port,
512 struct switchdev_obj_port_vlan *vlan,
513 int (*cb)(struct switchdev_obj *obj));
514int mv88e6xxx_port_fdb_prepare(struct dsa_switch *ds, int port,
515 const struct switchdev_obj_port_fdb *fdb,
516 struct switchdev_trans *trans);
517void mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port,
518 const struct switchdev_obj_port_fdb *fdb,
519 struct switchdev_trans *trans);
520int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port,
521 const struct switchdev_obj_port_fdb *fdb);
522int mv88e6xxx_port_fdb_dump(struct dsa_switch *ds, int port,
523 struct switchdev_obj_port_fdb *fdb,
524 int (*cb)(struct switchdev_obj *obj));
525int mv88e6xxx_phy_page_read(struct dsa_switch *ds, int port, int page, int reg);
526int mv88e6xxx_phy_page_write(struct dsa_switch *ds, int port, int page,
527 int reg, int val);
528
529extern struct dsa_switch_driver mv88e6131_switch_driver;
530extern struct dsa_switch_driver mv88e6123_switch_driver;
531extern struct dsa_switch_driver mv88e6352_switch_driver;
532extern struct dsa_switch_driver mv88e6171_switch_driver;
533 606
534#endif607#endif