1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Microchip KSZ9477 switch driver main logic
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2017-2019 Microchip Technology Inc.
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun #include <linux/kernel.h>
9*4882a593Smuzhiyun #include <linux/module.h>
10*4882a593Smuzhiyun #include <linux/iopoll.h>
11*4882a593Smuzhiyun #include <linux/platform_data/microchip-ksz.h>
12*4882a593Smuzhiyun #include <linux/phy.h>
13*4882a593Smuzhiyun #include <linux/if_bridge.h>
14*4882a593Smuzhiyun #include <net/dsa.h>
15*4882a593Smuzhiyun #include <net/switchdev.h>
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun #include "ksz9477_reg.h"
18*4882a593Smuzhiyun #include "ksz_common.h"
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun /* Used with variable features to indicate capabilities. */
21*4882a593Smuzhiyun #define GBIT_SUPPORT BIT(0)
22*4882a593Smuzhiyun #define NEW_XMII BIT(1)
23*4882a593Smuzhiyun #define IS_9893 BIT(2)
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun static const struct {
26*4882a593Smuzhiyun int index;
27*4882a593Smuzhiyun char string[ETH_GSTRING_LEN];
28*4882a593Smuzhiyun } ksz9477_mib_names[TOTAL_SWITCH_COUNTER_NUM] = {
29*4882a593Smuzhiyun { 0x00, "rx_hi" },
30*4882a593Smuzhiyun { 0x01, "rx_undersize" },
31*4882a593Smuzhiyun { 0x02, "rx_fragments" },
32*4882a593Smuzhiyun { 0x03, "rx_oversize" },
33*4882a593Smuzhiyun { 0x04, "rx_jabbers" },
34*4882a593Smuzhiyun { 0x05, "rx_symbol_err" },
35*4882a593Smuzhiyun { 0x06, "rx_crc_err" },
36*4882a593Smuzhiyun { 0x07, "rx_align_err" },
37*4882a593Smuzhiyun { 0x08, "rx_mac_ctrl" },
38*4882a593Smuzhiyun { 0x09, "rx_pause" },
39*4882a593Smuzhiyun { 0x0A, "rx_bcast" },
40*4882a593Smuzhiyun { 0x0B, "rx_mcast" },
41*4882a593Smuzhiyun { 0x0C, "rx_ucast" },
42*4882a593Smuzhiyun { 0x0D, "rx_64_or_less" },
43*4882a593Smuzhiyun { 0x0E, "rx_65_127" },
44*4882a593Smuzhiyun { 0x0F, "rx_128_255" },
45*4882a593Smuzhiyun { 0x10, "rx_256_511" },
46*4882a593Smuzhiyun { 0x11, "rx_512_1023" },
47*4882a593Smuzhiyun { 0x12, "rx_1024_1522" },
48*4882a593Smuzhiyun { 0x13, "rx_1523_2000" },
49*4882a593Smuzhiyun { 0x14, "rx_2001" },
50*4882a593Smuzhiyun { 0x15, "tx_hi" },
51*4882a593Smuzhiyun { 0x16, "tx_late_col" },
52*4882a593Smuzhiyun { 0x17, "tx_pause" },
53*4882a593Smuzhiyun { 0x18, "tx_bcast" },
54*4882a593Smuzhiyun { 0x19, "tx_mcast" },
55*4882a593Smuzhiyun { 0x1A, "tx_ucast" },
56*4882a593Smuzhiyun { 0x1B, "tx_deferred" },
57*4882a593Smuzhiyun { 0x1C, "tx_total_col" },
58*4882a593Smuzhiyun { 0x1D, "tx_exc_col" },
59*4882a593Smuzhiyun { 0x1E, "tx_single_col" },
60*4882a593Smuzhiyun { 0x1F, "tx_mult_col" },
61*4882a593Smuzhiyun { 0x80, "rx_total" },
62*4882a593Smuzhiyun { 0x81, "tx_total" },
63*4882a593Smuzhiyun { 0x82, "rx_discards" },
64*4882a593Smuzhiyun { 0x83, "tx_discards" },
65*4882a593Smuzhiyun };
66*4882a593Smuzhiyun
ksz_cfg(struct ksz_device * dev,u32 addr,u8 bits,bool set)67*4882a593Smuzhiyun static void ksz_cfg(struct ksz_device *dev, u32 addr, u8 bits, bool set)
68*4882a593Smuzhiyun {
69*4882a593Smuzhiyun regmap_update_bits(dev->regmap[0], addr, bits, set ? bits : 0);
70*4882a593Smuzhiyun }
71*4882a593Smuzhiyun
ksz_port_cfg(struct ksz_device * dev,int port,int offset,u8 bits,bool set)72*4882a593Smuzhiyun static void ksz_port_cfg(struct ksz_device *dev, int port, int offset, u8 bits,
73*4882a593Smuzhiyun bool set)
74*4882a593Smuzhiyun {
75*4882a593Smuzhiyun regmap_update_bits(dev->regmap[0], PORT_CTRL_ADDR(port, offset),
76*4882a593Smuzhiyun bits, set ? bits : 0);
77*4882a593Smuzhiyun }
78*4882a593Smuzhiyun
ksz9477_cfg32(struct ksz_device * dev,u32 addr,u32 bits,bool set)79*4882a593Smuzhiyun static void ksz9477_cfg32(struct ksz_device *dev, u32 addr, u32 bits, bool set)
80*4882a593Smuzhiyun {
81*4882a593Smuzhiyun regmap_update_bits(dev->regmap[2], addr, bits, set ? bits : 0);
82*4882a593Smuzhiyun }
83*4882a593Smuzhiyun
ksz9477_port_cfg32(struct ksz_device * dev,int port,int offset,u32 bits,bool set)84*4882a593Smuzhiyun static void ksz9477_port_cfg32(struct ksz_device *dev, int port, int offset,
85*4882a593Smuzhiyun u32 bits, bool set)
86*4882a593Smuzhiyun {
87*4882a593Smuzhiyun regmap_update_bits(dev->regmap[2], PORT_CTRL_ADDR(port, offset),
88*4882a593Smuzhiyun bits, set ? bits : 0);
89*4882a593Smuzhiyun }
90*4882a593Smuzhiyun
ksz9477_wait_vlan_ctrl_ready(struct ksz_device * dev)91*4882a593Smuzhiyun static int ksz9477_wait_vlan_ctrl_ready(struct ksz_device *dev)
92*4882a593Smuzhiyun {
93*4882a593Smuzhiyun unsigned int val;
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun return regmap_read_poll_timeout(dev->regmap[0], REG_SW_VLAN_CTRL,
96*4882a593Smuzhiyun val, !(val & VLAN_START), 10, 1000);
97*4882a593Smuzhiyun }
98*4882a593Smuzhiyun
ksz9477_get_vlan_table(struct ksz_device * dev,u16 vid,u32 * vlan_table)99*4882a593Smuzhiyun static int ksz9477_get_vlan_table(struct ksz_device *dev, u16 vid,
100*4882a593Smuzhiyun u32 *vlan_table)
101*4882a593Smuzhiyun {
102*4882a593Smuzhiyun int ret;
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun mutex_lock(&dev->vlan_mutex);
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun ksz_write16(dev, REG_SW_VLAN_ENTRY_INDEX__2, vid & VLAN_INDEX_M);
107*4882a593Smuzhiyun ksz_write8(dev, REG_SW_VLAN_CTRL, VLAN_READ | VLAN_START);
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun /* wait to be cleared */
110*4882a593Smuzhiyun ret = ksz9477_wait_vlan_ctrl_ready(dev);
111*4882a593Smuzhiyun if (ret) {
112*4882a593Smuzhiyun dev_dbg(dev->dev, "Failed to read vlan table\n");
113*4882a593Smuzhiyun goto exit;
114*4882a593Smuzhiyun }
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun ksz_read32(dev, REG_SW_VLAN_ENTRY__4, &vlan_table[0]);
117*4882a593Smuzhiyun ksz_read32(dev, REG_SW_VLAN_ENTRY_UNTAG__4, &vlan_table[1]);
118*4882a593Smuzhiyun ksz_read32(dev, REG_SW_VLAN_ENTRY_PORTS__4, &vlan_table[2]);
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun ksz_write8(dev, REG_SW_VLAN_CTRL, 0);
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun exit:
123*4882a593Smuzhiyun mutex_unlock(&dev->vlan_mutex);
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun return ret;
126*4882a593Smuzhiyun }
127*4882a593Smuzhiyun
ksz9477_set_vlan_table(struct ksz_device * dev,u16 vid,u32 * vlan_table)128*4882a593Smuzhiyun static int ksz9477_set_vlan_table(struct ksz_device *dev, u16 vid,
129*4882a593Smuzhiyun u32 *vlan_table)
130*4882a593Smuzhiyun {
131*4882a593Smuzhiyun int ret;
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun mutex_lock(&dev->vlan_mutex);
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun ksz_write32(dev, REG_SW_VLAN_ENTRY__4, vlan_table[0]);
136*4882a593Smuzhiyun ksz_write32(dev, REG_SW_VLAN_ENTRY_UNTAG__4, vlan_table[1]);
137*4882a593Smuzhiyun ksz_write32(dev, REG_SW_VLAN_ENTRY_PORTS__4, vlan_table[2]);
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun ksz_write16(dev, REG_SW_VLAN_ENTRY_INDEX__2, vid & VLAN_INDEX_M);
140*4882a593Smuzhiyun ksz_write8(dev, REG_SW_VLAN_CTRL, VLAN_START | VLAN_WRITE);
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun /* wait to be cleared */
143*4882a593Smuzhiyun ret = ksz9477_wait_vlan_ctrl_ready(dev);
144*4882a593Smuzhiyun if (ret) {
145*4882a593Smuzhiyun dev_dbg(dev->dev, "Failed to write vlan table\n");
146*4882a593Smuzhiyun goto exit;
147*4882a593Smuzhiyun }
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun ksz_write8(dev, REG_SW_VLAN_CTRL, 0);
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun /* update vlan cache table */
152*4882a593Smuzhiyun dev->vlan_cache[vid].table[0] = vlan_table[0];
153*4882a593Smuzhiyun dev->vlan_cache[vid].table[1] = vlan_table[1];
154*4882a593Smuzhiyun dev->vlan_cache[vid].table[2] = vlan_table[2];
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun exit:
157*4882a593Smuzhiyun mutex_unlock(&dev->vlan_mutex);
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun return ret;
160*4882a593Smuzhiyun }
161*4882a593Smuzhiyun
ksz9477_read_table(struct ksz_device * dev,u32 * table)162*4882a593Smuzhiyun static void ksz9477_read_table(struct ksz_device *dev, u32 *table)
163*4882a593Smuzhiyun {
164*4882a593Smuzhiyun ksz_read32(dev, REG_SW_ALU_VAL_A, &table[0]);
165*4882a593Smuzhiyun ksz_read32(dev, REG_SW_ALU_VAL_B, &table[1]);
166*4882a593Smuzhiyun ksz_read32(dev, REG_SW_ALU_VAL_C, &table[2]);
167*4882a593Smuzhiyun ksz_read32(dev, REG_SW_ALU_VAL_D, &table[3]);
168*4882a593Smuzhiyun }
169*4882a593Smuzhiyun
ksz9477_write_table(struct ksz_device * dev,u32 * table)170*4882a593Smuzhiyun static void ksz9477_write_table(struct ksz_device *dev, u32 *table)
171*4882a593Smuzhiyun {
172*4882a593Smuzhiyun ksz_write32(dev, REG_SW_ALU_VAL_A, table[0]);
173*4882a593Smuzhiyun ksz_write32(dev, REG_SW_ALU_VAL_B, table[1]);
174*4882a593Smuzhiyun ksz_write32(dev, REG_SW_ALU_VAL_C, table[2]);
175*4882a593Smuzhiyun ksz_write32(dev, REG_SW_ALU_VAL_D, table[3]);
176*4882a593Smuzhiyun }
177*4882a593Smuzhiyun
ksz9477_wait_alu_ready(struct ksz_device * dev)178*4882a593Smuzhiyun static int ksz9477_wait_alu_ready(struct ksz_device *dev)
179*4882a593Smuzhiyun {
180*4882a593Smuzhiyun unsigned int val;
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun return regmap_read_poll_timeout(dev->regmap[2], REG_SW_ALU_CTRL__4,
183*4882a593Smuzhiyun val, !(val & ALU_START), 10, 1000);
184*4882a593Smuzhiyun }
185*4882a593Smuzhiyun
ksz9477_wait_alu_sta_ready(struct ksz_device * dev)186*4882a593Smuzhiyun static int ksz9477_wait_alu_sta_ready(struct ksz_device *dev)
187*4882a593Smuzhiyun {
188*4882a593Smuzhiyun unsigned int val;
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun return regmap_read_poll_timeout(dev->regmap[2],
191*4882a593Smuzhiyun REG_SW_ALU_STAT_CTRL__4,
192*4882a593Smuzhiyun val, !(val & ALU_STAT_START),
193*4882a593Smuzhiyun 10, 1000);
194*4882a593Smuzhiyun }
195*4882a593Smuzhiyun
ksz9477_reset_switch(struct ksz_device * dev)196*4882a593Smuzhiyun static int ksz9477_reset_switch(struct ksz_device *dev)
197*4882a593Smuzhiyun {
198*4882a593Smuzhiyun u8 data8;
199*4882a593Smuzhiyun u32 data32;
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun /* reset switch */
202*4882a593Smuzhiyun ksz_cfg(dev, REG_SW_OPERATION, SW_RESET, true);
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun /* turn off SPI DO Edge select */
205*4882a593Smuzhiyun regmap_update_bits(dev->regmap[0], REG_SW_GLOBAL_SERIAL_CTRL_0,
206*4882a593Smuzhiyun SPI_AUTO_EDGE_DETECTION, 0);
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun /* default configuration */
209*4882a593Smuzhiyun ksz_read8(dev, REG_SW_LUE_CTRL_1, &data8);
210*4882a593Smuzhiyun data8 = SW_AGING_ENABLE | SW_LINK_AUTO_AGING |
211*4882a593Smuzhiyun SW_SRC_ADDR_FILTER | SW_FLUSH_STP_TABLE | SW_FLUSH_MSTP_TABLE;
212*4882a593Smuzhiyun ksz_write8(dev, REG_SW_LUE_CTRL_1, data8);
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun /* disable interrupts */
215*4882a593Smuzhiyun ksz_write32(dev, REG_SW_INT_MASK__4, SWITCH_INT_MASK);
216*4882a593Smuzhiyun ksz_write32(dev, REG_SW_PORT_INT_MASK__4, 0x7F);
217*4882a593Smuzhiyun ksz_read32(dev, REG_SW_PORT_INT_STATUS__4, &data32);
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun /* set broadcast storm protection 10% rate */
220*4882a593Smuzhiyun regmap_update_bits(dev->regmap[1], REG_SW_MAC_CTRL_2,
221*4882a593Smuzhiyun BROADCAST_STORM_RATE,
222*4882a593Smuzhiyun (BROADCAST_STORM_VALUE *
223*4882a593Smuzhiyun BROADCAST_STORM_PROT_RATE) / 100);
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun if (dev->synclko_125)
226*4882a593Smuzhiyun ksz_write8(dev, REG_SW_GLOBAL_OUTPUT_CTRL__1,
227*4882a593Smuzhiyun SW_ENABLE_REFCLKO | SW_REFCLKO_IS_125MHZ);
228*4882a593Smuzhiyun
229*4882a593Smuzhiyun return 0;
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun
ksz9477_r_mib_cnt(struct ksz_device * dev,int port,u16 addr,u64 * cnt)232*4882a593Smuzhiyun static void ksz9477_r_mib_cnt(struct ksz_device *dev, int port, u16 addr,
233*4882a593Smuzhiyun u64 *cnt)
234*4882a593Smuzhiyun {
235*4882a593Smuzhiyun struct ksz_port *p = &dev->ports[port];
236*4882a593Smuzhiyun unsigned int val;
237*4882a593Smuzhiyun u32 data;
238*4882a593Smuzhiyun int ret;
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun /* retain the flush/freeze bit */
241*4882a593Smuzhiyun data = p->freeze ? MIB_COUNTER_FLUSH_FREEZE : 0;
242*4882a593Smuzhiyun data |= MIB_COUNTER_READ;
243*4882a593Smuzhiyun data |= (addr << MIB_COUNTER_INDEX_S);
244*4882a593Smuzhiyun ksz_pwrite32(dev, port, REG_PORT_MIB_CTRL_STAT__4, data);
245*4882a593Smuzhiyun
246*4882a593Smuzhiyun ret = regmap_read_poll_timeout(dev->regmap[2],
247*4882a593Smuzhiyun PORT_CTRL_ADDR(port, REG_PORT_MIB_CTRL_STAT__4),
248*4882a593Smuzhiyun val, !(val & MIB_COUNTER_READ), 10, 1000);
249*4882a593Smuzhiyun /* failed to read MIB. get out of loop */
250*4882a593Smuzhiyun if (ret) {
251*4882a593Smuzhiyun dev_dbg(dev->dev, "Failed to get MIB\n");
252*4882a593Smuzhiyun return;
253*4882a593Smuzhiyun }
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun /* count resets upon read */
256*4882a593Smuzhiyun ksz_pread32(dev, port, REG_PORT_MIB_DATA, &data);
257*4882a593Smuzhiyun *cnt += data;
258*4882a593Smuzhiyun }
259*4882a593Smuzhiyun
ksz9477_r_mib_pkt(struct ksz_device * dev,int port,u16 addr,u64 * dropped,u64 * cnt)260*4882a593Smuzhiyun static void ksz9477_r_mib_pkt(struct ksz_device *dev, int port, u16 addr,
261*4882a593Smuzhiyun u64 *dropped, u64 *cnt)
262*4882a593Smuzhiyun {
263*4882a593Smuzhiyun addr = ksz9477_mib_names[addr].index;
264*4882a593Smuzhiyun ksz9477_r_mib_cnt(dev, port, addr, cnt);
265*4882a593Smuzhiyun }
266*4882a593Smuzhiyun
ksz9477_freeze_mib(struct ksz_device * dev,int port,bool freeze)267*4882a593Smuzhiyun static void ksz9477_freeze_mib(struct ksz_device *dev, int port, bool freeze)
268*4882a593Smuzhiyun {
269*4882a593Smuzhiyun u32 val = freeze ? MIB_COUNTER_FLUSH_FREEZE : 0;
270*4882a593Smuzhiyun struct ksz_port *p = &dev->ports[port];
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun /* enable/disable the port for flush/freeze function */
273*4882a593Smuzhiyun mutex_lock(&p->mib.cnt_mutex);
274*4882a593Smuzhiyun ksz_pwrite32(dev, port, REG_PORT_MIB_CTRL_STAT__4, val);
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun /* used by MIB counter reading code to know freeze is enabled */
277*4882a593Smuzhiyun p->freeze = freeze;
278*4882a593Smuzhiyun mutex_unlock(&p->mib.cnt_mutex);
279*4882a593Smuzhiyun }
280*4882a593Smuzhiyun
ksz9477_port_init_cnt(struct ksz_device * dev,int port)281*4882a593Smuzhiyun static void ksz9477_port_init_cnt(struct ksz_device *dev, int port)
282*4882a593Smuzhiyun {
283*4882a593Smuzhiyun struct ksz_port_mib *mib = &dev->ports[port].mib;
284*4882a593Smuzhiyun
285*4882a593Smuzhiyun /* flush all enabled port MIB counters */
286*4882a593Smuzhiyun mutex_lock(&mib->cnt_mutex);
287*4882a593Smuzhiyun ksz_pwrite32(dev, port, REG_PORT_MIB_CTRL_STAT__4,
288*4882a593Smuzhiyun MIB_COUNTER_FLUSH_FREEZE);
289*4882a593Smuzhiyun ksz_write8(dev, REG_SW_MAC_CTRL_6, SW_MIB_COUNTER_FLUSH);
290*4882a593Smuzhiyun ksz_pwrite32(dev, port, REG_PORT_MIB_CTRL_STAT__4, 0);
291*4882a593Smuzhiyun mutex_unlock(&mib->cnt_mutex);
292*4882a593Smuzhiyun
293*4882a593Smuzhiyun mib->cnt_ptr = 0;
294*4882a593Smuzhiyun memset(mib->counters, 0, dev->mib_cnt * sizeof(u64));
295*4882a593Smuzhiyun }
296*4882a593Smuzhiyun
ksz9477_get_tag_protocol(struct dsa_switch * ds,int port,enum dsa_tag_protocol mp)297*4882a593Smuzhiyun static enum dsa_tag_protocol ksz9477_get_tag_protocol(struct dsa_switch *ds,
298*4882a593Smuzhiyun int port,
299*4882a593Smuzhiyun enum dsa_tag_protocol mp)
300*4882a593Smuzhiyun {
301*4882a593Smuzhiyun enum dsa_tag_protocol proto = DSA_TAG_PROTO_KSZ9477;
302*4882a593Smuzhiyun struct ksz_device *dev = ds->priv;
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun if (dev->features & IS_9893)
305*4882a593Smuzhiyun proto = DSA_TAG_PROTO_KSZ9893;
306*4882a593Smuzhiyun return proto;
307*4882a593Smuzhiyun }
308*4882a593Smuzhiyun
ksz9477_phy_read16(struct dsa_switch * ds,int addr,int reg)309*4882a593Smuzhiyun static int ksz9477_phy_read16(struct dsa_switch *ds, int addr, int reg)
310*4882a593Smuzhiyun {
311*4882a593Smuzhiyun struct ksz_device *dev = ds->priv;
312*4882a593Smuzhiyun u16 val = 0xffff;
313*4882a593Smuzhiyun
314*4882a593Smuzhiyun /* No real PHY after this. Simulate the PHY.
315*4882a593Smuzhiyun * A fixed PHY can be setup in the device tree, but this function is
316*4882a593Smuzhiyun * still called for that port during initialization.
317*4882a593Smuzhiyun * For RGMII PHY there is no way to access it so the fixed PHY should
318*4882a593Smuzhiyun * be used. For SGMII PHY the supporting code will be added later.
319*4882a593Smuzhiyun */
320*4882a593Smuzhiyun if (addr >= dev->phy_port_cnt) {
321*4882a593Smuzhiyun struct ksz_port *p = &dev->ports[addr];
322*4882a593Smuzhiyun
323*4882a593Smuzhiyun switch (reg) {
324*4882a593Smuzhiyun case MII_BMCR:
325*4882a593Smuzhiyun val = 0x1140;
326*4882a593Smuzhiyun break;
327*4882a593Smuzhiyun case MII_BMSR:
328*4882a593Smuzhiyun val = 0x796d;
329*4882a593Smuzhiyun break;
330*4882a593Smuzhiyun case MII_PHYSID1:
331*4882a593Smuzhiyun val = 0x0022;
332*4882a593Smuzhiyun break;
333*4882a593Smuzhiyun case MII_PHYSID2:
334*4882a593Smuzhiyun val = 0x1631;
335*4882a593Smuzhiyun break;
336*4882a593Smuzhiyun case MII_ADVERTISE:
337*4882a593Smuzhiyun val = 0x05e1;
338*4882a593Smuzhiyun break;
339*4882a593Smuzhiyun case MII_LPA:
340*4882a593Smuzhiyun val = 0xc5e1;
341*4882a593Smuzhiyun break;
342*4882a593Smuzhiyun case MII_CTRL1000:
343*4882a593Smuzhiyun val = 0x0700;
344*4882a593Smuzhiyun break;
345*4882a593Smuzhiyun case MII_STAT1000:
346*4882a593Smuzhiyun if (p->phydev.speed == SPEED_1000)
347*4882a593Smuzhiyun val = 0x3800;
348*4882a593Smuzhiyun else
349*4882a593Smuzhiyun val = 0;
350*4882a593Smuzhiyun break;
351*4882a593Smuzhiyun }
352*4882a593Smuzhiyun } else {
353*4882a593Smuzhiyun ksz_pread16(dev, addr, 0x100 + (reg << 1), &val);
354*4882a593Smuzhiyun }
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun return val;
357*4882a593Smuzhiyun }
358*4882a593Smuzhiyun
ksz9477_phy_write16(struct dsa_switch * ds,int addr,int reg,u16 val)359*4882a593Smuzhiyun static int ksz9477_phy_write16(struct dsa_switch *ds, int addr, int reg,
360*4882a593Smuzhiyun u16 val)
361*4882a593Smuzhiyun {
362*4882a593Smuzhiyun struct ksz_device *dev = ds->priv;
363*4882a593Smuzhiyun
364*4882a593Smuzhiyun /* No real PHY after this. */
365*4882a593Smuzhiyun if (addr >= dev->phy_port_cnt)
366*4882a593Smuzhiyun return 0;
367*4882a593Smuzhiyun
368*4882a593Smuzhiyun /* No gigabit support. Do not write to this register. */
369*4882a593Smuzhiyun if (!(dev->features & GBIT_SUPPORT) && reg == MII_CTRL1000)
370*4882a593Smuzhiyun return 0;
371*4882a593Smuzhiyun ksz_pwrite16(dev, addr, 0x100 + (reg << 1), val);
372*4882a593Smuzhiyun
373*4882a593Smuzhiyun return 0;
374*4882a593Smuzhiyun }
375*4882a593Smuzhiyun
ksz9477_get_strings(struct dsa_switch * ds,int port,u32 stringset,uint8_t * buf)376*4882a593Smuzhiyun static void ksz9477_get_strings(struct dsa_switch *ds, int port,
377*4882a593Smuzhiyun u32 stringset, uint8_t *buf)
378*4882a593Smuzhiyun {
379*4882a593Smuzhiyun int i;
380*4882a593Smuzhiyun
381*4882a593Smuzhiyun if (stringset != ETH_SS_STATS)
382*4882a593Smuzhiyun return;
383*4882a593Smuzhiyun
384*4882a593Smuzhiyun for (i = 0; i < TOTAL_SWITCH_COUNTER_NUM; i++) {
385*4882a593Smuzhiyun memcpy(buf + i * ETH_GSTRING_LEN, ksz9477_mib_names[i].string,
386*4882a593Smuzhiyun ETH_GSTRING_LEN);
387*4882a593Smuzhiyun }
388*4882a593Smuzhiyun }
389*4882a593Smuzhiyun
ksz9477_cfg_port_member(struct ksz_device * dev,int port,u8 member)390*4882a593Smuzhiyun static void ksz9477_cfg_port_member(struct ksz_device *dev, int port,
391*4882a593Smuzhiyun u8 member)
392*4882a593Smuzhiyun {
393*4882a593Smuzhiyun ksz_pwrite32(dev, port, REG_PORT_VLAN_MEMBERSHIP__4, member);
394*4882a593Smuzhiyun dev->ports[port].member = member;
395*4882a593Smuzhiyun }
396*4882a593Smuzhiyun
ksz9477_port_stp_state_set(struct dsa_switch * ds,int port,u8 state)397*4882a593Smuzhiyun static void ksz9477_port_stp_state_set(struct dsa_switch *ds, int port,
398*4882a593Smuzhiyun u8 state)
399*4882a593Smuzhiyun {
400*4882a593Smuzhiyun struct ksz_device *dev = ds->priv;
401*4882a593Smuzhiyun struct ksz_port *p = &dev->ports[port];
402*4882a593Smuzhiyun u8 data;
403*4882a593Smuzhiyun int member = -1;
404*4882a593Smuzhiyun int forward = dev->member;
405*4882a593Smuzhiyun
406*4882a593Smuzhiyun ksz_pread8(dev, port, P_STP_CTRL, &data);
407*4882a593Smuzhiyun data &= ~(PORT_TX_ENABLE | PORT_RX_ENABLE | PORT_LEARN_DISABLE);
408*4882a593Smuzhiyun
409*4882a593Smuzhiyun switch (state) {
410*4882a593Smuzhiyun case BR_STATE_DISABLED:
411*4882a593Smuzhiyun data |= PORT_LEARN_DISABLE;
412*4882a593Smuzhiyun if (port != dev->cpu_port)
413*4882a593Smuzhiyun member = 0;
414*4882a593Smuzhiyun break;
415*4882a593Smuzhiyun case BR_STATE_LISTENING:
416*4882a593Smuzhiyun data |= (PORT_RX_ENABLE | PORT_LEARN_DISABLE);
417*4882a593Smuzhiyun if (port != dev->cpu_port &&
418*4882a593Smuzhiyun p->stp_state == BR_STATE_DISABLED)
419*4882a593Smuzhiyun member = dev->host_mask | p->vid_member;
420*4882a593Smuzhiyun break;
421*4882a593Smuzhiyun case BR_STATE_LEARNING:
422*4882a593Smuzhiyun data |= PORT_RX_ENABLE;
423*4882a593Smuzhiyun break;
424*4882a593Smuzhiyun case BR_STATE_FORWARDING:
425*4882a593Smuzhiyun data |= (PORT_TX_ENABLE | PORT_RX_ENABLE);
426*4882a593Smuzhiyun
427*4882a593Smuzhiyun /* This function is also used internally. */
428*4882a593Smuzhiyun if (port == dev->cpu_port)
429*4882a593Smuzhiyun break;
430*4882a593Smuzhiyun
431*4882a593Smuzhiyun member = dev->host_mask | p->vid_member;
432*4882a593Smuzhiyun mutex_lock(&dev->dev_mutex);
433*4882a593Smuzhiyun
434*4882a593Smuzhiyun /* Port is a member of a bridge. */
435*4882a593Smuzhiyun if (dev->br_member & (1 << port)) {
436*4882a593Smuzhiyun dev->member |= (1 << port);
437*4882a593Smuzhiyun member = dev->member;
438*4882a593Smuzhiyun }
439*4882a593Smuzhiyun mutex_unlock(&dev->dev_mutex);
440*4882a593Smuzhiyun break;
441*4882a593Smuzhiyun case BR_STATE_BLOCKING:
442*4882a593Smuzhiyun data |= PORT_LEARN_DISABLE;
443*4882a593Smuzhiyun if (port != dev->cpu_port &&
444*4882a593Smuzhiyun p->stp_state == BR_STATE_DISABLED)
445*4882a593Smuzhiyun member = dev->host_mask | p->vid_member;
446*4882a593Smuzhiyun break;
447*4882a593Smuzhiyun default:
448*4882a593Smuzhiyun dev_err(ds->dev, "invalid STP state: %d\n", state);
449*4882a593Smuzhiyun return;
450*4882a593Smuzhiyun }
451*4882a593Smuzhiyun
452*4882a593Smuzhiyun ksz_pwrite8(dev, port, P_STP_CTRL, data);
453*4882a593Smuzhiyun p->stp_state = state;
454*4882a593Smuzhiyun mutex_lock(&dev->dev_mutex);
455*4882a593Smuzhiyun /* Port membership may share register with STP state. */
456*4882a593Smuzhiyun if (member >= 0 && member != p->member)
457*4882a593Smuzhiyun ksz9477_cfg_port_member(dev, port, (u8)member);
458*4882a593Smuzhiyun
459*4882a593Smuzhiyun /* Check if forwarding needs to be updated. */
460*4882a593Smuzhiyun if (state != BR_STATE_FORWARDING) {
461*4882a593Smuzhiyun if (dev->br_member & (1 << port))
462*4882a593Smuzhiyun dev->member &= ~(1 << port);
463*4882a593Smuzhiyun }
464*4882a593Smuzhiyun
465*4882a593Smuzhiyun /* When topology has changed the function ksz_update_port_member
466*4882a593Smuzhiyun * should be called to modify port forwarding behavior.
467*4882a593Smuzhiyun */
468*4882a593Smuzhiyun if (forward != dev->member)
469*4882a593Smuzhiyun ksz_update_port_member(dev, port);
470*4882a593Smuzhiyun mutex_unlock(&dev->dev_mutex);
471*4882a593Smuzhiyun }
472*4882a593Smuzhiyun
ksz9477_flush_dyn_mac_table(struct ksz_device * dev,int port)473*4882a593Smuzhiyun static void ksz9477_flush_dyn_mac_table(struct ksz_device *dev, int port)
474*4882a593Smuzhiyun {
475*4882a593Smuzhiyun u8 data;
476*4882a593Smuzhiyun
477*4882a593Smuzhiyun regmap_update_bits(dev->regmap[0], REG_SW_LUE_CTRL_2,
478*4882a593Smuzhiyun SW_FLUSH_OPTION_M << SW_FLUSH_OPTION_S,
479*4882a593Smuzhiyun SW_FLUSH_OPTION_DYN_MAC << SW_FLUSH_OPTION_S);
480*4882a593Smuzhiyun
481*4882a593Smuzhiyun if (port < dev->mib_port_cnt) {
482*4882a593Smuzhiyun /* flush individual port */
483*4882a593Smuzhiyun ksz_pread8(dev, port, P_STP_CTRL, &data);
484*4882a593Smuzhiyun if (!(data & PORT_LEARN_DISABLE))
485*4882a593Smuzhiyun ksz_pwrite8(dev, port, P_STP_CTRL,
486*4882a593Smuzhiyun data | PORT_LEARN_DISABLE);
487*4882a593Smuzhiyun ksz_cfg(dev, S_FLUSH_TABLE_CTRL, SW_FLUSH_DYN_MAC_TABLE, true);
488*4882a593Smuzhiyun ksz_pwrite8(dev, port, P_STP_CTRL, data);
489*4882a593Smuzhiyun } else {
490*4882a593Smuzhiyun /* flush all */
491*4882a593Smuzhiyun ksz_cfg(dev, S_FLUSH_TABLE_CTRL, SW_FLUSH_STP_TABLE, true);
492*4882a593Smuzhiyun }
493*4882a593Smuzhiyun }
494*4882a593Smuzhiyun
ksz9477_port_vlan_filtering(struct dsa_switch * ds,int port,bool flag,struct switchdev_trans * trans)495*4882a593Smuzhiyun static int ksz9477_port_vlan_filtering(struct dsa_switch *ds, int port,
496*4882a593Smuzhiyun bool flag,
497*4882a593Smuzhiyun struct switchdev_trans *trans)
498*4882a593Smuzhiyun {
499*4882a593Smuzhiyun struct ksz_device *dev = ds->priv;
500*4882a593Smuzhiyun
501*4882a593Smuzhiyun if (switchdev_trans_ph_prepare(trans))
502*4882a593Smuzhiyun return 0;
503*4882a593Smuzhiyun
504*4882a593Smuzhiyun if (flag) {
505*4882a593Smuzhiyun ksz_port_cfg(dev, port, REG_PORT_LUE_CTRL,
506*4882a593Smuzhiyun PORT_VLAN_LOOKUP_VID_0, true);
507*4882a593Smuzhiyun ksz_cfg(dev, REG_SW_LUE_CTRL_0, SW_VLAN_ENABLE, true);
508*4882a593Smuzhiyun } else {
509*4882a593Smuzhiyun ksz_cfg(dev, REG_SW_LUE_CTRL_0, SW_VLAN_ENABLE, false);
510*4882a593Smuzhiyun ksz_port_cfg(dev, port, REG_PORT_LUE_CTRL,
511*4882a593Smuzhiyun PORT_VLAN_LOOKUP_VID_0, false);
512*4882a593Smuzhiyun }
513*4882a593Smuzhiyun
514*4882a593Smuzhiyun return 0;
515*4882a593Smuzhiyun }
516*4882a593Smuzhiyun
ksz9477_port_vlan_add(struct dsa_switch * ds,int port,const struct switchdev_obj_port_vlan * vlan)517*4882a593Smuzhiyun static void ksz9477_port_vlan_add(struct dsa_switch *ds, int port,
518*4882a593Smuzhiyun const struct switchdev_obj_port_vlan *vlan)
519*4882a593Smuzhiyun {
520*4882a593Smuzhiyun struct ksz_device *dev = ds->priv;
521*4882a593Smuzhiyun u32 vlan_table[3];
522*4882a593Smuzhiyun u16 vid;
523*4882a593Smuzhiyun bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
524*4882a593Smuzhiyun
525*4882a593Smuzhiyun for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) {
526*4882a593Smuzhiyun if (ksz9477_get_vlan_table(dev, vid, vlan_table)) {
527*4882a593Smuzhiyun dev_dbg(dev->dev, "Failed to get vlan table\n");
528*4882a593Smuzhiyun return;
529*4882a593Smuzhiyun }
530*4882a593Smuzhiyun
531*4882a593Smuzhiyun vlan_table[0] = VLAN_VALID | (vid & VLAN_FID_M);
532*4882a593Smuzhiyun if (untagged)
533*4882a593Smuzhiyun vlan_table[1] |= BIT(port);
534*4882a593Smuzhiyun else
535*4882a593Smuzhiyun vlan_table[1] &= ~BIT(port);
536*4882a593Smuzhiyun vlan_table[1] &= ~(BIT(dev->cpu_port));
537*4882a593Smuzhiyun
538*4882a593Smuzhiyun vlan_table[2] |= BIT(port) | BIT(dev->cpu_port);
539*4882a593Smuzhiyun
540*4882a593Smuzhiyun if (ksz9477_set_vlan_table(dev, vid, vlan_table)) {
541*4882a593Smuzhiyun dev_dbg(dev->dev, "Failed to set vlan table\n");
542*4882a593Smuzhiyun return;
543*4882a593Smuzhiyun }
544*4882a593Smuzhiyun
545*4882a593Smuzhiyun /* change PVID */
546*4882a593Smuzhiyun if (vlan->flags & BRIDGE_VLAN_INFO_PVID)
547*4882a593Smuzhiyun ksz_pwrite16(dev, port, REG_PORT_DEFAULT_VID, vid);
548*4882a593Smuzhiyun }
549*4882a593Smuzhiyun }
550*4882a593Smuzhiyun
ksz9477_port_vlan_del(struct dsa_switch * ds,int port,const struct switchdev_obj_port_vlan * vlan)551*4882a593Smuzhiyun static int ksz9477_port_vlan_del(struct dsa_switch *ds, int port,
552*4882a593Smuzhiyun const struct switchdev_obj_port_vlan *vlan)
553*4882a593Smuzhiyun {
554*4882a593Smuzhiyun struct ksz_device *dev = ds->priv;
555*4882a593Smuzhiyun bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
556*4882a593Smuzhiyun u32 vlan_table[3];
557*4882a593Smuzhiyun u16 vid;
558*4882a593Smuzhiyun u16 pvid;
559*4882a593Smuzhiyun
560*4882a593Smuzhiyun ksz_pread16(dev, port, REG_PORT_DEFAULT_VID, &pvid);
561*4882a593Smuzhiyun pvid = pvid & 0xFFF;
562*4882a593Smuzhiyun
563*4882a593Smuzhiyun for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) {
564*4882a593Smuzhiyun if (ksz9477_get_vlan_table(dev, vid, vlan_table)) {
565*4882a593Smuzhiyun dev_dbg(dev->dev, "Failed to get vlan table\n");
566*4882a593Smuzhiyun return -ETIMEDOUT;
567*4882a593Smuzhiyun }
568*4882a593Smuzhiyun
569*4882a593Smuzhiyun vlan_table[2] &= ~BIT(port);
570*4882a593Smuzhiyun
571*4882a593Smuzhiyun if (pvid == vid)
572*4882a593Smuzhiyun pvid = 1;
573*4882a593Smuzhiyun
574*4882a593Smuzhiyun if (untagged)
575*4882a593Smuzhiyun vlan_table[1] &= ~BIT(port);
576*4882a593Smuzhiyun
577*4882a593Smuzhiyun if (ksz9477_set_vlan_table(dev, vid, vlan_table)) {
578*4882a593Smuzhiyun dev_dbg(dev->dev, "Failed to set vlan table\n");
579*4882a593Smuzhiyun return -ETIMEDOUT;
580*4882a593Smuzhiyun }
581*4882a593Smuzhiyun }
582*4882a593Smuzhiyun
583*4882a593Smuzhiyun ksz_pwrite16(dev, port, REG_PORT_DEFAULT_VID, pvid);
584*4882a593Smuzhiyun
585*4882a593Smuzhiyun return 0;
586*4882a593Smuzhiyun }
587*4882a593Smuzhiyun
ksz9477_port_fdb_add(struct dsa_switch * ds,int port,const unsigned char * addr,u16 vid)588*4882a593Smuzhiyun static int ksz9477_port_fdb_add(struct dsa_switch *ds, int port,
589*4882a593Smuzhiyun const unsigned char *addr, u16 vid)
590*4882a593Smuzhiyun {
591*4882a593Smuzhiyun struct ksz_device *dev = ds->priv;
592*4882a593Smuzhiyun u32 alu_table[4];
593*4882a593Smuzhiyun u32 data;
594*4882a593Smuzhiyun int ret = 0;
595*4882a593Smuzhiyun
596*4882a593Smuzhiyun mutex_lock(&dev->alu_mutex);
597*4882a593Smuzhiyun
598*4882a593Smuzhiyun /* find any entry with mac & vid */
599*4882a593Smuzhiyun data = vid << ALU_FID_INDEX_S;
600*4882a593Smuzhiyun data |= ((addr[0] << 8) | addr[1]);
601*4882a593Smuzhiyun ksz_write32(dev, REG_SW_ALU_INDEX_0, data);
602*4882a593Smuzhiyun
603*4882a593Smuzhiyun data = ((addr[2] << 24) | (addr[3] << 16));
604*4882a593Smuzhiyun data |= ((addr[4] << 8) | addr[5]);
605*4882a593Smuzhiyun ksz_write32(dev, REG_SW_ALU_INDEX_1, data);
606*4882a593Smuzhiyun
607*4882a593Smuzhiyun /* start read operation */
608*4882a593Smuzhiyun ksz_write32(dev, REG_SW_ALU_CTRL__4, ALU_READ | ALU_START);
609*4882a593Smuzhiyun
610*4882a593Smuzhiyun /* wait to be finished */
611*4882a593Smuzhiyun ret = ksz9477_wait_alu_ready(dev);
612*4882a593Smuzhiyun if (ret) {
613*4882a593Smuzhiyun dev_dbg(dev->dev, "Failed to read ALU\n");
614*4882a593Smuzhiyun goto exit;
615*4882a593Smuzhiyun }
616*4882a593Smuzhiyun
617*4882a593Smuzhiyun /* read ALU entry */
618*4882a593Smuzhiyun ksz9477_read_table(dev, alu_table);
619*4882a593Smuzhiyun
620*4882a593Smuzhiyun /* update ALU entry */
621*4882a593Smuzhiyun alu_table[0] = ALU_V_STATIC_VALID;
622*4882a593Smuzhiyun alu_table[1] |= BIT(port);
623*4882a593Smuzhiyun if (vid)
624*4882a593Smuzhiyun alu_table[1] |= ALU_V_USE_FID;
625*4882a593Smuzhiyun alu_table[2] = (vid << ALU_V_FID_S);
626*4882a593Smuzhiyun alu_table[2] |= ((addr[0] << 8) | addr[1]);
627*4882a593Smuzhiyun alu_table[3] = ((addr[2] << 24) | (addr[3] << 16));
628*4882a593Smuzhiyun alu_table[3] |= ((addr[4] << 8) | addr[5]);
629*4882a593Smuzhiyun
630*4882a593Smuzhiyun ksz9477_write_table(dev, alu_table);
631*4882a593Smuzhiyun
632*4882a593Smuzhiyun ksz_write32(dev, REG_SW_ALU_CTRL__4, ALU_WRITE | ALU_START);
633*4882a593Smuzhiyun
634*4882a593Smuzhiyun /* wait to be finished */
635*4882a593Smuzhiyun ret = ksz9477_wait_alu_ready(dev);
636*4882a593Smuzhiyun if (ret)
637*4882a593Smuzhiyun dev_dbg(dev->dev, "Failed to write ALU\n");
638*4882a593Smuzhiyun
639*4882a593Smuzhiyun exit:
640*4882a593Smuzhiyun mutex_unlock(&dev->alu_mutex);
641*4882a593Smuzhiyun
642*4882a593Smuzhiyun return ret;
643*4882a593Smuzhiyun }
644*4882a593Smuzhiyun
ksz9477_port_fdb_del(struct dsa_switch * ds,int port,const unsigned char * addr,u16 vid)645*4882a593Smuzhiyun static int ksz9477_port_fdb_del(struct dsa_switch *ds, int port,
646*4882a593Smuzhiyun const unsigned char *addr, u16 vid)
647*4882a593Smuzhiyun {
648*4882a593Smuzhiyun struct ksz_device *dev = ds->priv;
649*4882a593Smuzhiyun u32 alu_table[4];
650*4882a593Smuzhiyun u32 data;
651*4882a593Smuzhiyun int ret = 0;
652*4882a593Smuzhiyun
653*4882a593Smuzhiyun mutex_lock(&dev->alu_mutex);
654*4882a593Smuzhiyun
655*4882a593Smuzhiyun /* read any entry with mac & vid */
656*4882a593Smuzhiyun data = vid << ALU_FID_INDEX_S;
657*4882a593Smuzhiyun data |= ((addr[0] << 8) | addr[1]);
658*4882a593Smuzhiyun ksz_write32(dev, REG_SW_ALU_INDEX_0, data);
659*4882a593Smuzhiyun
660*4882a593Smuzhiyun data = ((addr[2] << 24) | (addr[3] << 16));
661*4882a593Smuzhiyun data |= ((addr[4] << 8) | addr[5]);
662*4882a593Smuzhiyun ksz_write32(dev, REG_SW_ALU_INDEX_1, data);
663*4882a593Smuzhiyun
664*4882a593Smuzhiyun /* start read operation */
665*4882a593Smuzhiyun ksz_write32(dev, REG_SW_ALU_CTRL__4, ALU_READ | ALU_START);
666*4882a593Smuzhiyun
667*4882a593Smuzhiyun /* wait to be finished */
668*4882a593Smuzhiyun ret = ksz9477_wait_alu_ready(dev);
669*4882a593Smuzhiyun if (ret) {
670*4882a593Smuzhiyun dev_dbg(dev->dev, "Failed to read ALU\n");
671*4882a593Smuzhiyun goto exit;
672*4882a593Smuzhiyun }
673*4882a593Smuzhiyun
674*4882a593Smuzhiyun ksz_read32(dev, REG_SW_ALU_VAL_A, &alu_table[0]);
675*4882a593Smuzhiyun if (alu_table[0] & ALU_V_STATIC_VALID) {
676*4882a593Smuzhiyun ksz_read32(dev, REG_SW_ALU_VAL_B, &alu_table[1]);
677*4882a593Smuzhiyun ksz_read32(dev, REG_SW_ALU_VAL_C, &alu_table[2]);
678*4882a593Smuzhiyun ksz_read32(dev, REG_SW_ALU_VAL_D, &alu_table[3]);
679*4882a593Smuzhiyun
680*4882a593Smuzhiyun /* clear forwarding port */
681*4882a593Smuzhiyun alu_table[2] &= ~BIT(port);
682*4882a593Smuzhiyun
683*4882a593Smuzhiyun /* if there is no port to forward, clear table */
684*4882a593Smuzhiyun if ((alu_table[2] & ALU_V_PORT_MAP) == 0) {
685*4882a593Smuzhiyun alu_table[0] = 0;
686*4882a593Smuzhiyun alu_table[1] = 0;
687*4882a593Smuzhiyun alu_table[2] = 0;
688*4882a593Smuzhiyun alu_table[3] = 0;
689*4882a593Smuzhiyun }
690*4882a593Smuzhiyun } else {
691*4882a593Smuzhiyun alu_table[0] = 0;
692*4882a593Smuzhiyun alu_table[1] = 0;
693*4882a593Smuzhiyun alu_table[2] = 0;
694*4882a593Smuzhiyun alu_table[3] = 0;
695*4882a593Smuzhiyun }
696*4882a593Smuzhiyun
697*4882a593Smuzhiyun ksz9477_write_table(dev, alu_table);
698*4882a593Smuzhiyun
699*4882a593Smuzhiyun ksz_write32(dev, REG_SW_ALU_CTRL__4, ALU_WRITE | ALU_START);
700*4882a593Smuzhiyun
701*4882a593Smuzhiyun /* wait to be finished */
702*4882a593Smuzhiyun ret = ksz9477_wait_alu_ready(dev);
703*4882a593Smuzhiyun if (ret)
704*4882a593Smuzhiyun dev_dbg(dev->dev, "Failed to write ALU\n");
705*4882a593Smuzhiyun
706*4882a593Smuzhiyun exit:
707*4882a593Smuzhiyun mutex_unlock(&dev->alu_mutex);
708*4882a593Smuzhiyun
709*4882a593Smuzhiyun return ret;
710*4882a593Smuzhiyun }
711*4882a593Smuzhiyun
ksz9477_convert_alu(struct alu_struct * alu,u32 * alu_table)712*4882a593Smuzhiyun static void ksz9477_convert_alu(struct alu_struct *alu, u32 *alu_table)
713*4882a593Smuzhiyun {
714*4882a593Smuzhiyun alu->is_static = !!(alu_table[0] & ALU_V_STATIC_VALID);
715*4882a593Smuzhiyun alu->is_src_filter = !!(alu_table[0] & ALU_V_SRC_FILTER);
716*4882a593Smuzhiyun alu->is_dst_filter = !!(alu_table[0] & ALU_V_DST_FILTER);
717*4882a593Smuzhiyun alu->prio_age = (alu_table[0] >> ALU_V_PRIO_AGE_CNT_S) &
718*4882a593Smuzhiyun ALU_V_PRIO_AGE_CNT_M;
719*4882a593Smuzhiyun alu->mstp = alu_table[0] & ALU_V_MSTP_M;
720*4882a593Smuzhiyun
721*4882a593Smuzhiyun alu->is_override = !!(alu_table[1] & ALU_V_OVERRIDE);
722*4882a593Smuzhiyun alu->is_use_fid = !!(alu_table[1] & ALU_V_USE_FID);
723*4882a593Smuzhiyun alu->port_forward = alu_table[1] & ALU_V_PORT_MAP;
724*4882a593Smuzhiyun
725*4882a593Smuzhiyun alu->fid = (alu_table[2] >> ALU_V_FID_S) & ALU_V_FID_M;
726*4882a593Smuzhiyun
727*4882a593Smuzhiyun alu->mac[0] = (alu_table[2] >> 8) & 0xFF;
728*4882a593Smuzhiyun alu->mac[1] = alu_table[2] & 0xFF;
729*4882a593Smuzhiyun alu->mac[2] = (alu_table[3] >> 24) & 0xFF;
730*4882a593Smuzhiyun alu->mac[3] = (alu_table[3] >> 16) & 0xFF;
731*4882a593Smuzhiyun alu->mac[4] = (alu_table[3] >> 8) & 0xFF;
732*4882a593Smuzhiyun alu->mac[5] = alu_table[3] & 0xFF;
733*4882a593Smuzhiyun }
734*4882a593Smuzhiyun
ksz9477_port_fdb_dump(struct dsa_switch * ds,int port,dsa_fdb_dump_cb_t * cb,void * data)735*4882a593Smuzhiyun static int ksz9477_port_fdb_dump(struct dsa_switch *ds, int port,
736*4882a593Smuzhiyun dsa_fdb_dump_cb_t *cb, void *data)
737*4882a593Smuzhiyun {
738*4882a593Smuzhiyun struct ksz_device *dev = ds->priv;
739*4882a593Smuzhiyun int ret = 0;
740*4882a593Smuzhiyun u32 ksz_data;
741*4882a593Smuzhiyun u32 alu_table[4];
742*4882a593Smuzhiyun struct alu_struct alu;
743*4882a593Smuzhiyun int timeout;
744*4882a593Smuzhiyun
745*4882a593Smuzhiyun mutex_lock(&dev->alu_mutex);
746*4882a593Smuzhiyun
747*4882a593Smuzhiyun /* start ALU search */
748*4882a593Smuzhiyun ksz_write32(dev, REG_SW_ALU_CTRL__4, ALU_START | ALU_SEARCH);
749*4882a593Smuzhiyun
750*4882a593Smuzhiyun do {
751*4882a593Smuzhiyun timeout = 1000;
752*4882a593Smuzhiyun do {
753*4882a593Smuzhiyun ksz_read32(dev, REG_SW_ALU_CTRL__4, &ksz_data);
754*4882a593Smuzhiyun if ((ksz_data & ALU_VALID) || !(ksz_data & ALU_START))
755*4882a593Smuzhiyun break;
756*4882a593Smuzhiyun usleep_range(1, 10);
757*4882a593Smuzhiyun } while (timeout-- > 0);
758*4882a593Smuzhiyun
759*4882a593Smuzhiyun if (!timeout) {
760*4882a593Smuzhiyun dev_dbg(dev->dev, "Failed to search ALU\n");
761*4882a593Smuzhiyun ret = -ETIMEDOUT;
762*4882a593Smuzhiyun goto exit;
763*4882a593Smuzhiyun }
764*4882a593Smuzhiyun
765*4882a593Smuzhiyun if (!(ksz_data & ALU_VALID))
766*4882a593Smuzhiyun continue;
767*4882a593Smuzhiyun
768*4882a593Smuzhiyun /* read ALU table */
769*4882a593Smuzhiyun ksz9477_read_table(dev, alu_table);
770*4882a593Smuzhiyun
771*4882a593Smuzhiyun ksz9477_convert_alu(&alu, alu_table);
772*4882a593Smuzhiyun
773*4882a593Smuzhiyun if (alu.port_forward & BIT(port)) {
774*4882a593Smuzhiyun ret = cb(alu.mac, alu.fid, alu.is_static, data);
775*4882a593Smuzhiyun if (ret)
776*4882a593Smuzhiyun goto exit;
777*4882a593Smuzhiyun }
778*4882a593Smuzhiyun } while (ksz_data & ALU_START);
779*4882a593Smuzhiyun
780*4882a593Smuzhiyun exit:
781*4882a593Smuzhiyun
782*4882a593Smuzhiyun /* stop ALU search */
783*4882a593Smuzhiyun ksz_write32(dev, REG_SW_ALU_CTRL__4, 0);
784*4882a593Smuzhiyun
785*4882a593Smuzhiyun mutex_unlock(&dev->alu_mutex);
786*4882a593Smuzhiyun
787*4882a593Smuzhiyun return ret;
788*4882a593Smuzhiyun }
789*4882a593Smuzhiyun
ksz9477_port_mdb_add(struct dsa_switch * ds,int port,const struct switchdev_obj_port_mdb * mdb)790*4882a593Smuzhiyun static void ksz9477_port_mdb_add(struct dsa_switch *ds, int port,
791*4882a593Smuzhiyun const struct switchdev_obj_port_mdb *mdb)
792*4882a593Smuzhiyun {
793*4882a593Smuzhiyun struct ksz_device *dev = ds->priv;
794*4882a593Smuzhiyun u32 static_table[4];
795*4882a593Smuzhiyun u32 data;
796*4882a593Smuzhiyun int index;
797*4882a593Smuzhiyun u32 mac_hi, mac_lo;
798*4882a593Smuzhiyun
799*4882a593Smuzhiyun mac_hi = ((mdb->addr[0] << 8) | mdb->addr[1]);
800*4882a593Smuzhiyun mac_lo = ((mdb->addr[2] << 24) | (mdb->addr[3] << 16));
801*4882a593Smuzhiyun mac_lo |= ((mdb->addr[4] << 8) | mdb->addr[5]);
802*4882a593Smuzhiyun
803*4882a593Smuzhiyun mutex_lock(&dev->alu_mutex);
804*4882a593Smuzhiyun
805*4882a593Smuzhiyun for (index = 0; index < dev->num_statics; index++) {
806*4882a593Smuzhiyun /* find empty slot first */
807*4882a593Smuzhiyun data = (index << ALU_STAT_INDEX_S) |
808*4882a593Smuzhiyun ALU_STAT_READ | ALU_STAT_START;
809*4882a593Smuzhiyun ksz_write32(dev, REG_SW_ALU_STAT_CTRL__4, data);
810*4882a593Smuzhiyun
811*4882a593Smuzhiyun /* wait to be finished */
812*4882a593Smuzhiyun if (ksz9477_wait_alu_sta_ready(dev)) {
813*4882a593Smuzhiyun dev_dbg(dev->dev, "Failed to read ALU STATIC\n");
814*4882a593Smuzhiyun goto exit;
815*4882a593Smuzhiyun }
816*4882a593Smuzhiyun
817*4882a593Smuzhiyun /* read ALU static table */
818*4882a593Smuzhiyun ksz9477_read_table(dev, static_table);
819*4882a593Smuzhiyun
820*4882a593Smuzhiyun if (static_table[0] & ALU_V_STATIC_VALID) {
821*4882a593Smuzhiyun /* check this has same vid & mac address */
822*4882a593Smuzhiyun if (((static_table[2] >> ALU_V_FID_S) == mdb->vid) &&
823*4882a593Smuzhiyun ((static_table[2] & ALU_V_MAC_ADDR_HI) == mac_hi) &&
824*4882a593Smuzhiyun static_table[3] == mac_lo) {
825*4882a593Smuzhiyun /* found matching one */
826*4882a593Smuzhiyun break;
827*4882a593Smuzhiyun }
828*4882a593Smuzhiyun } else {
829*4882a593Smuzhiyun /* found empty one */
830*4882a593Smuzhiyun break;
831*4882a593Smuzhiyun }
832*4882a593Smuzhiyun }
833*4882a593Smuzhiyun
834*4882a593Smuzhiyun /* no available entry */
835*4882a593Smuzhiyun if (index == dev->num_statics)
836*4882a593Smuzhiyun goto exit;
837*4882a593Smuzhiyun
838*4882a593Smuzhiyun /* add entry */
839*4882a593Smuzhiyun static_table[0] = ALU_V_STATIC_VALID;
840*4882a593Smuzhiyun static_table[1] |= BIT(port);
841*4882a593Smuzhiyun if (mdb->vid)
842*4882a593Smuzhiyun static_table[1] |= ALU_V_USE_FID;
843*4882a593Smuzhiyun static_table[2] = (mdb->vid << ALU_V_FID_S);
844*4882a593Smuzhiyun static_table[2] |= mac_hi;
845*4882a593Smuzhiyun static_table[3] = mac_lo;
846*4882a593Smuzhiyun
847*4882a593Smuzhiyun ksz9477_write_table(dev, static_table);
848*4882a593Smuzhiyun
849*4882a593Smuzhiyun data = (index << ALU_STAT_INDEX_S) | ALU_STAT_START;
850*4882a593Smuzhiyun ksz_write32(dev, REG_SW_ALU_STAT_CTRL__4, data);
851*4882a593Smuzhiyun
852*4882a593Smuzhiyun /* wait to be finished */
853*4882a593Smuzhiyun if (ksz9477_wait_alu_sta_ready(dev))
854*4882a593Smuzhiyun dev_dbg(dev->dev, "Failed to read ALU STATIC\n");
855*4882a593Smuzhiyun
856*4882a593Smuzhiyun exit:
857*4882a593Smuzhiyun mutex_unlock(&dev->alu_mutex);
858*4882a593Smuzhiyun }
859*4882a593Smuzhiyun
ksz9477_port_mdb_del(struct dsa_switch * ds,int port,const struct switchdev_obj_port_mdb * mdb)860*4882a593Smuzhiyun static int ksz9477_port_mdb_del(struct dsa_switch *ds, int port,
861*4882a593Smuzhiyun const struct switchdev_obj_port_mdb *mdb)
862*4882a593Smuzhiyun {
863*4882a593Smuzhiyun struct ksz_device *dev = ds->priv;
864*4882a593Smuzhiyun u32 static_table[4];
865*4882a593Smuzhiyun u32 data;
866*4882a593Smuzhiyun int index;
867*4882a593Smuzhiyun int ret = 0;
868*4882a593Smuzhiyun u32 mac_hi, mac_lo;
869*4882a593Smuzhiyun
870*4882a593Smuzhiyun mac_hi = ((mdb->addr[0] << 8) | mdb->addr[1]);
871*4882a593Smuzhiyun mac_lo = ((mdb->addr[2] << 24) | (mdb->addr[3] << 16));
872*4882a593Smuzhiyun mac_lo |= ((mdb->addr[4] << 8) | mdb->addr[5]);
873*4882a593Smuzhiyun
874*4882a593Smuzhiyun mutex_lock(&dev->alu_mutex);
875*4882a593Smuzhiyun
876*4882a593Smuzhiyun for (index = 0; index < dev->num_statics; index++) {
877*4882a593Smuzhiyun /* find empty slot first */
878*4882a593Smuzhiyun data = (index << ALU_STAT_INDEX_S) |
879*4882a593Smuzhiyun ALU_STAT_READ | ALU_STAT_START;
880*4882a593Smuzhiyun ksz_write32(dev, REG_SW_ALU_STAT_CTRL__4, data);
881*4882a593Smuzhiyun
882*4882a593Smuzhiyun /* wait to be finished */
883*4882a593Smuzhiyun ret = ksz9477_wait_alu_sta_ready(dev);
884*4882a593Smuzhiyun if (ret) {
885*4882a593Smuzhiyun dev_dbg(dev->dev, "Failed to read ALU STATIC\n");
886*4882a593Smuzhiyun goto exit;
887*4882a593Smuzhiyun }
888*4882a593Smuzhiyun
889*4882a593Smuzhiyun /* read ALU static table */
890*4882a593Smuzhiyun ksz9477_read_table(dev, static_table);
891*4882a593Smuzhiyun
892*4882a593Smuzhiyun if (static_table[0] & ALU_V_STATIC_VALID) {
893*4882a593Smuzhiyun /* check this has same vid & mac address */
894*4882a593Smuzhiyun
895*4882a593Smuzhiyun if (((static_table[2] >> ALU_V_FID_S) == mdb->vid) &&
896*4882a593Smuzhiyun ((static_table[2] & ALU_V_MAC_ADDR_HI) == mac_hi) &&
897*4882a593Smuzhiyun static_table[3] == mac_lo) {
898*4882a593Smuzhiyun /* found matching one */
899*4882a593Smuzhiyun break;
900*4882a593Smuzhiyun }
901*4882a593Smuzhiyun }
902*4882a593Smuzhiyun }
903*4882a593Smuzhiyun
904*4882a593Smuzhiyun /* no available entry */
905*4882a593Smuzhiyun if (index == dev->num_statics)
906*4882a593Smuzhiyun goto exit;
907*4882a593Smuzhiyun
908*4882a593Smuzhiyun /* clear port */
909*4882a593Smuzhiyun static_table[1] &= ~BIT(port);
910*4882a593Smuzhiyun
911*4882a593Smuzhiyun if ((static_table[1] & ALU_V_PORT_MAP) == 0) {
912*4882a593Smuzhiyun /* delete entry */
913*4882a593Smuzhiyun static_table[0] = 0;
914*4882a593Smuzhiyun static_table[1] = 0;
915*4882a593Smuzhiyun static_table[2] = 0;
916*4882a593Smuzhiyun static_table[3] = 0;
917*4882a593Smuzhiyun }
918*4882a593Smuzhiyun
919*4882a593Smuzhiyun ksz9477_write_table(dev, static_table);
920*4882a593Smuzhiyun
921*4882a593Smuzhiyun data = (index << ALU_STAT_INDEX_S) | ALU_STAT_START;
922*4882a593Smuzhiyun ksz_write32(dev, REG_SW_ALU_STAT_CTRL__4, data);
923*4882a593Smuzhiyun
924*4882a593Smuzhiyun /* wait to be finished */
925*4882a593Smuzhiyun ret = ksz9477_wait_alu_sta_ready(dev);
926*4882a593Smuzhiyun if (ret)
927*4882a593Smuzhiyun dev_dbg(dev->dev, "Failed to read ALU STATIC\n");
928*4882a593Smuzhiyun
929*4882a593Smuzhiyun exit:
930*4882a593Smuzhiyun mutex_unlock(&dev->alu_mutex);
931*4882a593Smuzhiyun
932*4882a593Smuzhiyun return ret;
933*4882a593Smuzhiyun }
934*4882a593Smuzhiyun
ksz9477_port_mirror_add(struct dsa_switch * ds,int port,struct dsa_mall_mirror_tc_entry * mirror,bool ingress)935*4882a593Smuzhiyun static int ksz9477_port_mirror_add(struct dsa_switch *ds, int port,
936*4882a593Smuzhiyun struct dsa_mall_mirror_tc_entry *mirror,
937*4882a593Smuzhiyun bool ingress)
938*4882a593Smuzhiyun {
939*4882a593Smuzhiyun struct ksz_device *dev = ds->priv;
940*4882a593Smuzhiyun
941*4882a593Smuzhiyun if (ingress)
942*4882a593Smuzhiyun ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_RX, true);
943*4882a593Smuzhiyun else
944*4882a593Smuzhiyun ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_TX, true);
945*4882a593Smuzhiyun
946*4882a593Smuzhiyun ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_SNIFFER, false);
947*4882a593Smuzhiyun
948*4882a593Smuzhiyun /* configure mirror port */
949*4882a593Smuzhiyun ksz_port_cfg(dev, mirror->to_local_port, P_MIRROR_CTRL,
950*4882a593Smuzhiyun PORT_MIRROR_SNIFFER, true);
951*4882a593Smuzhiyun
952*4882a593Smuzhiyun ksz_cfg(dev, S_MIRROR_CTRL, SW_MIRROR_RX_TX, false);
953*4882a593Smuzhiyun
954*4882a593Smuzhiyun return 0;
955*4882a593Smuzhiyun }
956*4882a593Smuzhiyun
ksz9477_port_mirror_del(struct dsa_switch * ds,int port,struct dsa_mall_mirror_tc_entry * mirror)957*4882a593Smuzhiyun static void ksz9477_port_mirror_del(struct dsa_switch *ds, int port,
958*4882a593Smuzhiyun struct dsa_mall_mirror_tc_entry *mirror)
959*4882a593Smuzhiyun {
960*4882a593Smuzhiyun struct ksz_device *dev = ds->priv;
961*4882a593Smuzhiyun u8 data;
962*4882a593Smuzhiyun
963*4882a593Smuzhiyun if (mirror->ingress)
964*4882a593Smuzhiyun ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_RX, false);
965*4882a593Smuzhiyun else
966*4882a593Smuzhiyun ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_TX, false);
967*4882a593Smuzhiyun
968*4882a593Smuzhiyun ksz_pread8(dev, port, P_MIRROR_CTRL, &data);
969*4882a593Smuzhiyun
970*4882a593Smuzhiyun if (!(data & (PORT_MIRROR_RX | PORT_MIRROR_TX)))
971*4882a593Smuzhiyun ksz_port_cfg(dev, mirror->to_local_port, P_MIRROR_CTRL,
972*4882a593Smuzhiyun PORT_MIRROR_SNIFFER, false);
973*4882a593Smuzhiyun }
974*4882a593Smuzhiyun
ksz9477_get_gbit(struct ksz_device * dev,u8 data)975*4882a593Smuzhiyun static bool ksz9477_get_gbit(struct ksz_device *dev, u8 data)
976*4882a593Smuzhiyun {
977*4882a593Smuzhiyun bool gbit;
978*4882a593Smuzhiyun
979*4882a593Smuzhiyun if (dev->features & NEW_XMII)
980*4882a593Smuzhiyun gbit = !(data & PORT_MII_NOT_1GBIT);
981*4882a593Smuzhiyun else
982*4882a593Smuzhiyun gbit = !!(data & PORT_MII_1000MBIT_S1);
983*4882a593Smuzhiyun return gbit;
984*4882a593Smuzhiyun }
985*4882a593Smuzhiyun
ksz9477_set_gbit(struct ksz_device * dev,bool gbit,u8 * data)986*4882a593Smuzhiyun static void ksz9477_set_gbit(struct ksz_device *dev, bool gbit, u8 *data)
987*4882a593Smuzhiyun {
988*4882a593Smuzhiyun if (dev->features & NEW_XMII) {
989*4882a593Smuzhiyun if (gbit)
990*4882a593Smuzhiyun *data &= ~PORT_MII_NOT_1GBIT;
991*4882a593Smuzhiyun else
992*4882a593Smuzhiyun *data |= PORT_MII_NOT_1GBIT;
993*4882a593Smuzhiyun } else {
994*4882a593Smuzhiyun if (gbit)
995*4882a593Smuzhiyun *data |= PORT_MII_1000MBIT_S1;
996*4882a593Smuzhiyun else
997*4882a593Smuzhiyun *data &= ~PORT_MII_1000MBIT_S1;
998*4882a593Smuzhiyun }
999*4882a593Smuzhiyun }
1000*4882a593Smuzhiyun
ksz9477_get_xmii(struct ksz_device * dev,u8 data)1001*4882a593Smuzhiyun static int ksz9477_get_xmii(struct ksz_device *dev, u8 data)
1002*4882a593Smuzhiyun {
1003*4882a593Smuzhiyun int mode;
1004*4882a593Smuzhiyun
1005*4882a593Smuzhiyun if (dev->features & NEW_XMII) {
1006*4882a593Smuzhiyun switch (data & PORT_MII_SEL_M) {
1007*4882a593Smuzhiyun case PORT_MII_SEL:
1008*4882a593Smuzhiyun mode = 0;
1009*4882a593Smuzhiyun break;
1010*4882a593Smuzhiyun case PORT_RMII_SEL:
1011*4882a593Smuzhiyun mode = 1;
1012*4882a593Smuzhiyun break;
1013*4882a593Smuzhiyun case PORT_GMII_SEL:
1014*4882a593Smuzhiyun mode = 2;
1015*4882a593Smuzhiyun break;
1016*4882a593Smuzhiyun default:
1017*4882a593Smuzhiyun mode = 3;
1018*4882a593Smuzhiyun }
1019*4882a593Smuzhiyun } else {
1020*4882a593Smuzhiyun switch (data & PORT_MII_SEL_M) {
1021*4882a593Smuzhiyun case PORT_MII_SEL_S1:
1022*4882a593Smuzhiyun mode = 0;
1023*4882a593Smuzhiyun break;
1024*4882a593Smuzhiyun case PORT_RMII_SEL_S1:
1025*4882a593Smuzhiyun mode = 1;
1026*4882a593Smuzhiyun break;
1027*4882a593Smuzhiyun case PORT_GMII_SEL_S1:
1028*4882a593Smuzhiyun mode = 2;
1029*4882a593Smuzhiyun break;
1030*4882a593Smuzhiyun default:
1031*4882a593Smuzhiyun mode = 3;
1032*4882a593Smuzhiyun }
1033*4882a593Smuzhiyun }
1034*4882a593Smuzhiyun return mode;
1035*4882a593Smuzhiyun }
1036*4882a593Smuzhiyun
ksz9477_set_xmii(struct ksz_device * dev,int mode,u8 * data)1037*4882a593Smuzhiyun static void ksz9477_set_xmii(struct ksz_device *dev, int mode, u8 *data)
1038*4882a593Smuzhiyun {
1039*4882a593Smuzhiyun u8 xmii;
1040*4882a593Smuzhiyun
1041*4882a593Smuzhiyun if (dev->features & NEW_XMII) {
1042*4882a593Smuzhiyun switch (mode) {
1043*4882a593Smuzhiyun case 0:
1044*4882a593Smuzhiyun xmii = PORT_MII_SEL;
1045*4882a593Smuzhiyun break;
1046*4882a593Smuzhiyun case 1:
1047*4882a593Smuzhiyun xmii = PORT_RMII_SEL;
1048*4882a593Smuzhiyun break;
1049*4882a593Smuzhiyun case 2:
1050*4882a593Smuzhiyun xmii = PORT_GMII_SEL;
1051*4882a593Smuzhiyun break;
1052*4882a593Smuzhiyun default:
1053*4882a593Smuzhiyun xmii = PORT_RGMII_SEL;
1054*4882a593Smuzhiyun break;
1055*4882a593Smuzhiyun }
1056*4882a593Smuzhiyun } else {
1057*4882a593Smuzhiyun switch (mode) {
1058*4882a593Smuzhiyun case 0:
1059*4882a593Smuzhiyun xmii = PORT_MII_SEL_S1;
1060*4882a593Smuzhiyun break;
1061*4882a593Smuzhiyun case 1:
1062*4882a593Smuzhiyun xmii = PORT_RMII_SEL_S1;
1063*4882a593Smuzhiyun break;
1064*4882a593Smuzhiyun case 2:
1065*4882a593Smuzhiyun xmii = PORT_GMII_SEL_S1;
1066*4882a593Smuzhiyun break;
1067*4882a593Smuzhiyun default:
1068*4882a593Smuzhiyun xmii = PORT_RGMII_SEL_S1;
1069*4882a593Smuzhiyun break;
1070*4882a593Smuzhiyun }
1071*4882a593Smuzhiyun }
1072*4882a593Smuzhiyun *data &= ~PORT_MII_SEL_M;
1073*4882a593Smuzhiyun *data |= xmii;
1074*4882a593Smuzhiyun }
1075*4882a593Smuzhiyun
ksz9477_get_interface(struct ksz_device * dev,int port)1076*4882a593Smuzhiyun static phy_interface_t ksz9477_get_interface(struct ksz_device *dev, int port)
1077*4882a593Smuzhiyun {
1078*4882a593Smuzhiyun phy_interface_t interface;
1079*4882a593Smuzhiyun bool gbit;
1080*4882a593Smuzhiyun int mode;
1081*4882a593Smuzhiyun u8 data8;
1082*4882a593Smuzhiyun
1083*4882a593Smuzhiyun if (port < dev->phy_port_cnt)
1084*4882a593Smuzhiyun return PHY_INTERFACE_MODE_NA;
1085*4882a593Smuzhiyun ksz_pread8(dev, port, REG_PORT_XMII_CTRL_1, &data8);
1086*4882a593Smuzhiyun gbit = ksz9477_get_gbit(dev, data8);
1087*4882a593Smuzhiyun mode = ksz9477_get_xmii(dev, data8);
1088*4882a593Smuzhiyun switch (mode) {
1089*4882a593Smuzhiyun case 2:
1090*4882a593Smuzhiyun interface = PHY_INTERFACE_MODE_GMII;
1091*4882a593Smuzhiyun if (gbit)
1092*4882a593Smuzhiyun break;
1093*4882a593Smuzhiyun fallthrough;
1094*4882a593Smuzhiyun case 0:
1095*4882a593Smuzhiyun interface = PHY_INTERFACE_MODE_MII;
1096*4882a593Smuzhiyun break;
1097*4882a593Smuzhiyun case 1:
1098*4882a593Smuzhiyun interface = PHY_INTERFACE_MODE_RMII;
1099*4882a593Smuzhiyun break;
1100*4882a593Smuzhiyun default:
1101*4882a593Smuzhiyun interface = PHY_INTERFACE_MODE_RGMII;
1102*4882a593Smuzhiyun if (data8 & PORT_RGMII_ID_EG_ENABLE)
1103*4882a593Smuzhiyun interface = PHY_INTERFACE_MODE_RGMII_TXID;
1104*4882a593Smuzhiyun if (data8 & PORT_RGMII_ID_IG_ENABLE) {
1105*4882a593Smuzhiyun interface = PHY_INTERFACE_MODE_RGMII_RXID;
1106*4882a593Smuzhiyun if (data8 & PORT_RGMII_ID_EG_ENABLE)
1107*4882a593Smuzhiyun interface = PHY_INTERFACE_MODE_RGMII_ID;
1108*4882a593Smuzhiyun }
1109*4882a593Smuzhiyun break;
1110*4882a593Smuzhiyun }
1111*4882a593Smuzhiyun return interface;
1112*4882a593Smuzhiyun }
1113*4882a593Smuzhiyun
ksz9477_port_mmd_write(struct ksz_device * dev,int port,u8 dev_addr,u16 reg_addr,u16 val)1114*4882a593Smuzhiyun static void ksz9477_port_mmd_write(struct ksz_device *dev, int port,
1115*4882a593Smuzhiyun u8 dev_addr, u16 reg_addr, u16 val)
1116*4882a593Smuzhiyun {
1117*4882a593Smuzhiyun ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_SETUP,
1118*4882a593Smuzhiyun MMD_SETUP(PORT_MMD_OP_INDEX, dev_addr));
1119*4882a593Smuzhiyun ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_INDEX_DATA, reg_addr);
1120*4882a593Smuzhiyun ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_SETUP,
1121*4882a593Smuzhiyun MMD_SETUP(PORT_MMD_OP_DATA_NO_INCR, dev_addr));
1122*4882a593Smuzhiyun ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_INDEX_DATA, val);
1123*4882a593Smuzhiyun }
1124*4882a593Smuzhiyun
ksz9477_phy_errata_setup(struct ksz_device * dev,int port)1125*4882a593Smuzhiyun static void ksz9477_phy_errata_setup(struct ksz_device *dev, int port)
1126*4882a593Smuzhiyun {
1127*4882a593Smuzhiyun /* Apply PHY settings to address errata listed in
1128*4882a593Smuzhiyun * KSZ9477, KSZ9897, KSZ9896, KSZ9567, KSZ8565
1129*4882a593Smuzhiyun * Silicon Errata and Data Sheet Clarification documents:
1130*4882a593Smuzhiyun *
1131*4882a593Smuzhiyun * Register settings are needed to improve PHY receive performance
1132*4882a593Smuzhiyun */
1133*4882a593Smuzhiyun ksz9477_port_mmd_write(dev, port, 0x01, 0x6f, 0xdd0b);
1134*4882a593Smuzhiyun ksz9477_port_mmd_write(dev, port, 0x01, 0x8f, 0x6032);
1135*4882a593Smuzhiyun ksz9477_port_mmd_write(dev, port, 0x01, 0x9d, 0x248c);
1136*4882a593Smuzhiyun ksz9477_port_mmd_write(dev, port, 0x01, 0x75, 0x0060);
1137*4882a593Smuzhiyun ksz9477_port_mmd_write(dev, port, 0x01, 0xd3, 0x7777);
1138*4882a593Smuzhiyun ksz9477_port_mmd_write(dev, port, 0x1c, 0x06, 0x3008);
1139*4882a593Smuzhiyun ksz9477_port_mmd_write(dev, port, 0x1c, 0x08, 0x2001);
1140*4882a593Smuzhiyun
1141*4882a593Smuzhiyun /* Transmit waveform amplitude can be improved
1142*4882a593Smuzhiyun * (1000BASE-T, 100BASE-TX, 10BASE-Te)
1143*4882a593Smuzhiyun */
1144*4882a593Smuzhiyun ksz9477_port_mmd_write(dev, port, 0x1c, 0x04, 0x00d0);
1145*4882a593Smuzhiyun
1146*4882a593Smuzhiyun /* Energy Efficient Ethernet (EEE) feature select must
1147*4882a593Smuzhiyun * be manually disabled (except on KSZ8565 which is 100Mbit)
1148*4882a593Smuzhiyun */
1149*4882a593Smuzhiyun if (dev->features & GBIT_SUPPORT)
1150*4882a593Smuzhiyun ksz9477_port_mmd_write(dev, port, 0x07, 0x3c, 0x0000);
1151*4882a593Smuzhiyun
1152*4882a593Smuzhiyun /* Register settings are required to meet data sheet
1153*4882a593Smuzhiyun * supply current specifications
1154*4882a593Smuzhiyun */
1155*4882a593Smuzhiyun ksz9477_port_mmd_write(dev, port, 0x1c, 0x13, 0x6eff);
1156*4882a593Smuzhiyun ksz9477_port_mmd_write(dev, port, 0x1c, 0x14, 0xe6ff);
1157*4882a593Smuzhiyun ksz9477_port_mmd_write(dev, port, 0x1c, 0x15, 0x6eff);
1158*4882a593Smuzhiyun ksz9477_port_mmd_write(dev, port, 0x1c, 0x16, 0xe6ff);
1159*4882a593Smuzhiyun ksz9477_port_mmd_write(dev, port, 0x1c, 0x17, 0x00ff);
1160*4882a593Smuzhiyun ksz9477_port_mmd_write(dev, port, 0x1c, 0x18, 0x43ff);
1161*4882a593Smuzhiyun ksz9477_port_mmd_write(dev, port, 0x1c, 0x19, 0xc3ff);
1162*4882a593Smuzhiyun ksz9477_port_mmd_write(dev, port, 0x1c, 0x1a, 0x6fff);
1163*4882a593Smuzhiyun ksz9477_port_mmd_write(dev, port, 0x1c, 0x1b, 0x07ff);
1164*4882a593Smuzhiyun ksz9477_port_mmd_write(dev, port, 0x1c, 0x1c, 0x0fff);
1165*4882a593Smuzhiyun ksz9477_port_mmd_write(dev, port, 0x1c, 0x1d, 0xe7ff);
1166*4882a593Smuzhiyun ksz9477_port_mmd_write(dev, port, 0x1c, 0x1e, 0xefff);
1167*4882a593Smuzhiyun ksz9477_port_mmd_write(dev, port, 0x1c, 0x20, 0xeeee);
1168*4882a593Smuzhiyun }
1169*4882a593Smuzhiyun
ksz9477_port_setup(struct ksz_device * dev,int port,bool cpu_port)1170*4882a593Smuzhiyun static void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port)
1171*4882a593Smuzhiyun {
1172*4882a593Smuzhiyun u8 data8;
1173*4882a593Smuzhiyun u8 member;
1174*4882a593Smuzhiyun u16 data16;
1175*4882a593Smuzhiyun struct ksz_port *p = &dev->ports[port];
1176*4882a593Smuzhiyun
1177*4882a593Smuzhiyun /* enable tag tail for host port */
1178*4882a593Smuzhiyun if (cpu_port)
1179*4882a593Smuzhiyun ksz_port_cfg(dev, port, REG_PORT_CTRL_0, PORT_TAIL_TAG_ENABLE,
1180*4882a593Smuzhiyun true);
1181*4882a593Smuzhiyun
1182*4882a593Smuzhiyun ksz_port_cfg(dev, port, REG_PORT_CTRL_0, PORT_MAC_LOOPBACK, false);
1183*4882a593Smuzhiyun
1184*4882a593Smuzhiyun /* set back pressure */
1185*4882a593Smuzhiyun ksz_port_cfg(dev, port, REG_PORT_MAC_CTRL_1, PORT_BACK_PRESSURE, true);
1186*4882a593Smuzhiyun
1187*4882a593Smuzhiyun /* enable broadcast storm limit */
1188*4882a593Smuzhiyun ksz_port_cfg(dev, port, P_BCAST_STORM_CTRL, PORT_BROADCAST_STORM, true);
1189*4882a593Smuzhiyun
1190*4882a593Smuzhiyun /* disable DiffServ priority */
1191*4882a593Smuzhiyun ksz_port_cfg(dev, port, P_PRIO_CTRL, PORT_DIFFSERV_PRIO_ENABLE, false);
1192*4882a593Smuzhiyun
1193*4882a593Smuzhiyun /* replace priority */
1194*4882a593Smuzhiyun ksz_port_cfg(dev, port, REG_PORT_MRI_MAC_CTRL, PORT_USER_PRIO_CEILING,
1195*4882a593Smuzhiyun false);
1196*4882a593Smuzhiyun ksz9477_port_cfg32(dev, port, REG_PORT_MTI_QUEUE_CTRL_0__4,
1197*4882a593Smuzhiyun MTI_PVID_REPLACE, false);
1198*4882a593Smuzhiyun
1199*4882a593Smuzhiyun /* enable 802.1p priority */
1200*4882a593Smuzhiyun ksz_port_cfg(dev, port, P_PRIO_CTRL, PORT_802_1P_PRIO_ENABLE, true);
1201*4882a593Smuzhiyun
1202*4882a593Smuzhiyun if (port < dev->phy_port_cnt) {
1203*4882a593Smuzhiyun /* do not force flow control */
1204*4882a593Smuzhiyun ksz_port_cfg(dev, port, REG_PORT_CTRL_0,
1205*4882a593Smuzhiyun PORT_FORCE_TX_FLOW_CTRL | PORT_FORCE_RX_FLOW_CTRL,
1206*4882a593Smuzhiyun false);
1207*4882a593Smuzhiyun
1208*4882a593Smuzhiyun if (dev->phy_errata_9477)
1209*4882a593Smuzhiyun ksz9477_phy_errata_setup(dev, port);
1210*4882a593Smuzhiyun } else {
1211*4882a593Smuzhiyun /* force flow control */
1212*4882a593Smuzhiyun ksz_port_cfg(dev, port, REG_PORT_CTRL_0,
1213*4882a593Smuzhiyun PORT_FORCE_TX_FLOW_CTRL | PORT_FORCE_RX_FLOW_CTRL,
1214*4882a593Smuzhiyun true);
1215*4882a593Smuzhiyun
1216*4882a593Smuzhiyun /* configure MAC to 1G & RGMII mode */
1217*4882a593Smuzhiyun ksz_pread8(dev, port, REG_PORT_XMII_CTRL_1, &data8);
1218*4882a593Smuzhiyun switch (p->interface) {
1219*4882a593Smuzhiyun case PHY_INTERFACE_MODE_MII:
1220*4882a593Smuzhiyun ksz9477_set_xmii(dev, 0, &data8);
1221*4882a593Smuzhiyun ksz9477_set_gbit(dev, false, &data8);
1222*4882a593Smuzhiyun p->phydev.speed = SPEED_100;
1223*4882a593Smuzhiyun break;
1224*4882a593Smuzhiyun case PHY_INTERFACE_MODE_RMII:
1225*4882a593Smuzhiyun ksz9477_set_xmii(dev, 1, &data8);
1226*4882a593Smuzhiyun ksz9477_set_gbit(dev, false, &data8);
1227*4882a593Smuzhiyun p->phydev.speed = SPEED_100;
1228*4882a593Smuzhiyun break;
1229*4882a593Smuzhiyun case PHY_INTERFACE_MODE_GMII:
1230*4882a593Smuzhiyun ksz9477_set_xmii(dev, 2, &data8);
1231*4882a593Smuzhiyun ksz9477_set_gbit(dev, true, &data8);
1232*4882a593Smuzhiyun p->phydev.speed = SPEED_1000;
1233*4882a593Smuzhiyun break;
1234*4882a593Smuzhiyun default:
1235*4882a593Smuzhiyun ksz9477_set_xmii(dev, 3, &data8);
1236*4882a593Smuzhiyun ksz9477_set_gbit(dev, true, &data8);
1237*4882a593Smuzhiyun data8 &= ~PORT_RGMII_ID_IG_ENABLE;
1238*4882a593Smuzhiyun data8 &= ~PORT_RGMII_ID_EG_ENABLE;
1239*4882a593Smuzhiyun if (p->interface == PHY_INTERFACE_MODE_RGMII_ID ||
1240*4882a593Smuzhiyun p->interface == PHY_INTERFACE_MODE_RGMII_RXID)
1241*4882a593Smuzhiyun data8 |= PORT_RGMII_ID_IG_ENABLE;
1242*4882a593Smuzhiyun if (p->interface == PHY_INTERFACE_MODE_RGMII_ID ||
1243*4882a593Smuzhiyun p->interface == PHY_INTERFACE_MODE_RGMII_TXID)
1244*4882a593Smuzhiyun data8 |= PORT_RGMII_ID_EG_ENABLE;
1245*4882a593Smuzhiyun /* On KSZ9893, disable RGMII in-band status support */
1246*4882a593Smuzhiyun if (dev->features & IS_9893)
1247*4882a593Smuzhiyun data8 &= ~PORT_MII_MAC_MODE;
1248*4882a593Smuzhiyun p->phydev.speed = SPEED_1000;
1249*4882a593Smuzhiyun break;
1250*4882a593Smuzhiyun }
1251*4882a593Smuzhiyun ksz_pwrite8(dev, port, REG_PORT_XMII_CTRL_1, data8);
1252*4882a593Smuzhiyun p->phydev.duplex = 1;
1253*4882a593Smuzhiyun }
1254*4882a593Smuzhiyun mutex_lock(&dev->dev_mutex);
1255*4882a593Smuzhiyun if (cpu_port)
1256*4882a593Smuzhiyun member = dev->port_mask;
1257*4882a593Smuzhiyun else
1258*4882a593Smuzhiyun member = dev->host_mask | p->vid_member;
1259*4882a593Smuzhiyun mutex_unlock(&dev->dev_mutex);
1260*4882a593Smuzhiyun ksz9477_cfg_port_member(dev, port, member);
1261*4882a593Smuzhiyun
1262*4882a593Smuzhiyun /* clear pending interrupts */
1263*4882a593Smuzhiyun if (port < dev->phy_port_cnt)
1264*4882a593Smuzhiyun ksz_pread16(dev, port, REG_PORT_PHY_INT_ENABLE, &data16);
1265*4882a593Smuzhiyun }
1266*4882a593Smuzhiyun
ksz9477_config_cpu_port(struct dsa_switch * ds)1267*4882a593Smuzhiyun static void ksz9477_config_cpu_port(struct dsa_switch *ds)
1268*4882a593Smuzhiyun {
1269*4882a593Smuzhiyun struct ksz_device *dev = ds->priv;
1270*4882a593Smuzhiyun struct ksz_port *p;
1271*4882a593Smuzhiyun int i;
1272*4882a593Smuzhiyun
1273*4882a593Smuzhiyun ds->num_ports = dev->port_cnt;
1274*4882a593Smuzhiyun
1275*4882a593Smuzhiyun for (i = 0; i < dev->port_cnt; i++) {
1276*4882a593Smuzhiyun if (dsa_is_cpu_port(ds, i) && (dev->cpu_ports & (1 << i))) {
1277*4882a593Smuzhiyun phy_interface_t interface;
1278*4882a593Smuzhiyun const char *prev_msg;
1279*4882a593Smuzhiyun const char *prev_mode;
1280*4882a593Smuzhiyun
1281*4882a593Smuzhiyun dev->cpu_port = i;
1282*4882a593Smuzhiyun dev->host_mask = (1 << dev->cpu_port);
1283*4882a593Smuzhiyun dev->port_mask |= dev->host_mask;
1284*4882a593Smuzhiyun p = &dev->ports[i];
1285*4882a593Smuzhiyun
1286*4882a593Smuzhiyun /* Read from XMII register to determine host port
1287*4882a593Smuzhiyun * interface. If set specifically in device tree
1288*4882a593Smuzhiyun * note the difference to help debugging.
1289*4882a593Smuzhiyun */
1290*4882a593Smuzhiyun interface = ksz9477_get_interface(dev, i);
1291*4882a593Smuzhiyun if (!p->interface) {
1292*4882a593Smuzhiyun if (dev->compat_interface) {
1293*4882a593Smuzhiyun dev_warn(dev->dev,
1294*4882a593Smuzhiyun "Using legacy switch \"phy-mode\" property, because it is missing on port %d node. "
1295*4882a593Smuzhiyun "Please update your device tree.\n",
1296*4882a593Smuzhiyun i);
1297*4882a593Smuzhiyun p->interface = dev->compat_interface;
1298*4882a593Smuzhiyun } else {
1299*4882a593Smuzhiyun p->interface = interface;
1300*4882a593Smuzhiyun }
1301*4882a593Smuzhiyun }
1302*4882a593Smuzhiyun if (interface && interface != p->interface) {
1303*4882a593Smuzhiyun prev_msg = " instead of ";
1304*4882a593Smuzhiyun prev_mode = phy_modes(interface);
1305*4882a593Smuzhiyun } else {
1306*4882a593Smuzhiyun prev_msg = "";
1307*4882a593Smuzhiyun prev_mode = "";
1308*4882a593Smuzhiyun }
1309*4882a593Smuzhiyun dev_info(dev->dev,
1310*4882a593Smuzhiyun "Port%d: using phy mode %s%s%s\n",
1311*4882a593Smuzhiyun i,
1312*4882a593Smuzhiyun phy_modes(p->interface),
1313*4882a593Smuzhiyun prev_msg,
1314*4882a593Smuzhiyun prev_mode);
1315*4882a593Smuzhiyun
1316*4882a593Smuzhiyun /* enable cpu port */
1317*4882a593Smuzhiyun ksz9477_port_setup(dev, i, true);
1318*4882a593Smuzhiyun p->vid_member = dev->port_mask;
1319*4882a593Smuzhiyun p->on = 1;
1320*4882a593Smuzhiyun }
1321*4882a593Smuzhiyun }
1322*4882a593Smuzhiyun
1323*4882a593Smuzhiyun dev->member = dev->host_mask;
1324*4882a593Smuzhiyun
1325*4882a593Smuzhiyun for (i = 0; i < dev->mib_port_cnt; i++) {
1326*4882a593Smuzhiyun if (i == dev->cpu_port)
1327*4882a593Smuzhiyun continue;
1328*4882a593Smuzhiyun p = &dev->ports[i];
1329*4882a593Smuzhiyun
1330*4882a593Smuzhiyun /* Initialize to non-zero so that ksz_cfg_port_member() will
1331*4882a593Smuzhiyun * be called.
1332*4882a593Smuzhiyun */
1333*4882a593Smuzhiyun p->vid_member = (1 << i);
1334*4882a593Smuzhiyun p->member = dev->port_mask;
1335*4882a593Smuzhiyun ksz9477_port_stp_state_set(ds, i, BR_STATE_DISABLED);
1336*4882a593Smuzhiyun p->on = 1;
1337*4882a593Smuzhiyun if (i < dev->phy_port_cnt)
1338*4882a593Smuzhiyun p->phy = 1;
1339*4882a593Smuzhiyun if (dev->chip_id == 0x00947700 && i == 6) {
1340*4882a593Smuzhiyun p->sgmii = 1;
1341*4882a593Smuzhiyun
1342*4882a593Smuzhiyun /* SGMII PHY detection code is not implemented yet. */
1343*4882a593Smuzhiyun p->phy = 0;
1344*4882a593Smuzhiyun }
1345*4882a593Smuzhiyun }
1346*4882a593Smuzhiyun }
1347*4882a593Smuzhiyun
ksz9477_setup(struct dsa_switch * ds)1348*4882a593Smuzhiyun static int ksz9477_setup(struct dsa_switch *ds)
1349*4882a593Smuzhiyun {
1350*4882a593Smuzhiyun struct ksz_device *dev = ds->priv;
1351*4882a593Smuzhiyun int ret = 0;
1352*4882a593Smuzhiyun
1353*4882a593Smuzhiyun dev->vlan_cache = devm_kcalloc(dev->dev, sizeof(struct vlan_table),
1354*4882a593Smuzhiyun dev->num_vlans, GFP_KERNEL);
1355*4882a593Smuzhiyun if (!dev->vlan_cache)
1356*4882a593Smuzhiyun return -ENOMEM;
1357*4882a593Smuzhiyun
1358*4882a593Smuzhiyun ret = ksz9477_reset_switch(dev);
1359*4882a593Smuzhiyun if (ret) {
1360*4882a593Smuzhiyun dev_err(ds->dev, "failed to reset switch\n");
1361*4882a593Smuzhiyun return ret;
1362*4882a593Smuzhiyun }
1363*4882a593Smuzhiyun
1364*4882a593Smuzhiyun /* Required for port partitioning. */
1365*4882a593Smuzhiyun ksz9477_cfg32(dev, REG_SW_QM_CTRL__4, UNICAST_VLAN_BOUNDARY,
1366*4882a593Smuzhiyun true);
1367*4882a593Smuzhiyun
1368*4882a593Smuzhiyun /* Do not work correctly with tail tagging. */
1369*4882a593Smuzhiyun ksz_cfg(dev, REG_SW_MAC_CTRL_0, SW_CHECK_LENGTH, false);
1370*4882a593Smuzhiyun
1371*4882a593Smuzhiyun /* accept packet up to 2000bytes */
1372*4882a593Smuzhiyun ksz_cfg(dev, REG_SW_MAC_CTRL_1, SW_LEGAL_PACKET_DISABLE, true);
1373*4882a593Smuzhiyun
1374*4882a593Smuzhiyun ksz9477_config_cpu_port(ds);
1375*4882a593Smuzhiyun
1376*4882a593Smuzhiyun ksz_cfg(dev, REG_SW_MAC_CTRL_1, MULTICAST_STORM_DISABLE, true);
1377*4882a593Smuzhiyun
1378*4882a593Smuzhiyun /* queue based egress rate limit */
1379*4882a593Smuzhiyun ksz_cfg(dev, REG_SW_MAC_CTRL_5, SW_OUT_RATE_LIMIT_QUEUE_BASED, true);
1380*4882a593Smuzhiyun
1381*4882a593Smuzhiyun /* enable global MIB counter freeze function */
1382*4882a593Smuzhiyun ksz_cfg(dev, REG_SW_MAC_CTRL_6, SW_MIB_COUNTER_FREEZE, true);
1383*4882a593Smuzhiyun
1384*4882a593Smuzhiyun /* start switch */
1385*4882a593Smuzhiyun ksz_cfg(dev, REG_SW_OPERATION, SW_START, true);
1386*4882a593Smuzhiyun
1387*4882a593Smuzhiyun ksz_init_mib_timer(dev);
1388*4882a593Smuzhiyun
1389*4882a593Smuzhiyun return 0;
1390*4882a593Smuzhiyun }
1391*4882a593Smuzhiyun
1392*4882a593Smuzhiyun static const struct dsa_switch_ops ksz9477_switch_ops = {
1393*4882a593Smuzhiyun .get_tag_protocol = ksz9477_get_tag_protocol,
1394*4882a593Smuzhiyun .setup = ksz9477_setup,
1395*4882a593Smuzhiyun .phy_read = ksz9477_phy_read16,
1396*4882a593Smuzhiyun .phy_write = ksz9477_phy_write16,
1397*4882a593Smuzhiyun .phylink_mac_link_down = ksz_mac_link_down,
1398*4882a593Smuzhiyun .port_enable = ksz_enable_port,
1399*4882a593Smuzhiyun .get_strings = ksz9477_get_strings,
1400*4882a593Smuzhiyun .get_ethtool_stats = ksz_get_ethtool_stats,
1401*4882a593Smuzhiyun .get_sset_count = ksz_sset_count,
1402*4882a593Smuzhiyun .port_bridge_join = ksz_port_bridge_join,
1403*4882a593Smuzhiyun .port_bridge_leave = ksz_port_bridge_leave,
1404*4882a593Smuzhiyun .port_stp_state_set = ksz9477_port_stp_state_set,
1405*4882a593Smuzhiyun .port_fast_age = ksz_port_fast_age,
1406*4882a593Smuzhiyun .port_vlan_filtering = ksz9477_port_vlan_filtering,
1407*4882a593Smuzhiyun .port_vlan_prepare = ksz_port_vlan_prepare,
1408*4882a593Smuzhiyun .port_vlan_add = ksz9477_port_vlan_add,
1409*4882a593Smuzhiyun .port_vlan_del = ksz9477_port_vlan_del,
1410*4882a593Smuzhiyun .port_fdb_dump = ksz9477_port_fdb_dump,
1411*4882a593Smuzhiyun .port_fdb_add = ksz9477_port_fdb_add,
1412*4882a593Smuzhiyun .port_fdb_del = ksz9477_port_fdb_del,
1413*4882a593Smuzhiyun .port_mdb_prepare = ksz_port_mdb_prepare,
1414*4882a593Smuzhiyun .port_mdb_add = ksz9477_port_mdb_add,
1415*4882a593Smuzhiyun .port_mdb_del = ksz9477_port_mdb_del,
1416*4882a593Smuzhiyun .port_mirror_add = ksz9477_port_mirror_add,
1417*4882a593Smuzhiyun .port_mirror_del = ksz9477_port_mirror_del,
1418*4882a593Smuzhiyun };
1419*4882a593Smuzhiyun
ksz9477_get_port_addr(int port,int offset)1420*4882a593Smuzhiyun static u32 ksz9477_get_port_addr(int port, int offset)
1421*4882a593Smuzhiyun {
1422*4882a593Smuzhiyun return PORT_CTRL_ADDR(port, offset);
1423*4882a593Smuzhiyun }
1424*4882a593Smuzhiyun
ksz9477_switch_detect(struct ksz_device * dev)1425*4882a593Smuzhiyun static int ksz9477_switch_detect(struct ksz_device *dev)
1426*4882a593Smuzhiyun {
1427*4882a593Smuzhiyun u8 data8;
1428*4882a593Smuzhiyun u8 id_hi;
1429*4882a593Smuzhiyun u8 id_lo;
1430*4882a593Smuzhiyun u32 id32;
1431*4882a593Smuzhiyun int ret;
1432*4882a593Smuzhiyun
1433*4882a593Smuzhiyun /* turn off SPI DO Edge select */
1434*4882a593Smuzhiyun ret = ksz_read8(dev, REG_SW_GLOBAL_SERIAL_CTRL_0, &data8);
1435*4882a593Smuzhiyun if (ret)
1436*4882a593Smuzhiyun return ret;
1437*4882a593Smuzhiyun
1438*4882a593Smuzhiyun data8 &= ~SPI_AUTO_EDGE_DETECTION;
1439*4882a593Smuzhiyun ret = ksz_write8(dev, REG_SW_GLOBAL_SERIAL_CTRL_0, data8);
1440*4882a593Smuzhiyun if (ret)
1441*4882a593Smuzhiyun return ret;
1442*4882a593Smuzhiyun
1443*4882a593Smuzhiyun /* read chip id */
1444*4882a593Smuzhiyun ret = ksz_read32(dev, REG_CHIP_ID0__1, &id32);
1445*4882a593Smuzhiyun if (ret)
1446*4882a593Smuzhiyun return ret;
1447*4882a593Smuzhiyun ret = ksz_read8(dev, REG_GLOBAL_OPTIONS, &data8);
1448*4882a593Smuzhiyun if (ret)
1449*4882a593Smuzhiyun return ret;
1450*4882a593Smuzhiyun
1451*4882a593Smuzhiyun /* Number of ports can be reduced depending on chip. */
1452*4882a593Smuzhiyun dev->mib_port_cnt = TOTAL_PORT_NUM;
1453*4882a593Smuzhiyun dev->phy_port_cnt = 5;
1454*4882a593Smuzhiyun
1455*4882a593Smuzhiyun /* Default capability is gigabit capable. */
1456*4882a593Smuzhiyun dev->features = GBIT_SUPPORT;
1457*4882a593Smuzhiyun
1458*4882a593Smuzhiyun dev_dbg(dev->dev, "Switch detect: ID=%08x%02x\n", id32, data8);
1459*4882a593Smuzhiyun id_hi = (u8)(id32 >> 16);
1460*4882a593Smuzhiyun id_lo = (u8)(id32 >> 8);
1461*4882a593Smuzhiyun if ((id_lo & 0xf) == 3) {
1462*4882a593Smuzhiyun /* Chip is from KSZ9893 design. */
1463*4882a593Smuzhiyun dev_info(dev->dev, "Found KSZ9893\n");
1464*4882a593Smuzhiyun dev->features |= IS_9893;
1465*4882a593Smuzhiyun
1466*4882a593Smuzhiyun /* Chip does not support gigabit. */
1467*4882a593Smuzhiyun if (data8 & SW_QW_ABLE)
1468*4882a593Smuzhiyun dev->features &= ~GBIT_SUPPORT;
1469*4882a593Smuzhiyun dev->mib_port_cnt = 3;
1470*4882a593Smuzhiyun dev->phy_port_cnt = 2;
1471*4882a593Smuzhiyun } else {
1472*4882a593Smuzhiyun dev_info(dev->dev, "Found KSZ9477 or compatible\n");
1473*4882a593Smuzhiyun /* Chip uses new XMII register definitions. */
1474*4882a593Smuzhiyun dev->features |= NEW_XMII;
1475*4882a593Smuzhiyun
1476*4882a593Smuzhiyun /* Chip does not support gigabit. */
1477*4882a593Smuzhiyun if (!(data8 & SW_GIGABIT_ABLE))
1478*4882a593Smuzhiyun dev->features &= ~GBIT_SUPPORT;
1479*4882a593Smuzhiyun }
1480*4882a593Smuzhiyun
1481*4882a593Smuzhiyun /* Change chip id to known ones so it can be matched against them. */
1482*4882a593Smuzhiyun id32 = (id_hi << 16) | (id_lo << 8);
1483*4882a593Smuzhiyun
1484*4882a593Smuzhiyun dev->chip_id = id32;
1485*4882a593Smuzhiyun
1486*4882a593Smuzhiyun return 0;
1487*4882a593Smuzhiyun }
1488*4882a593Smuzhiyun
1489*4882a593Smuzhiyun struct ksz_chip_data {
1490*4882a593Smuzhiyun u32 chip_id;
1491*4882a593Smuzhiyun const char *dev_name;
1492*4882a593Smuzhiyun int num_vlans;
1493*4882a593Smuzhiyun int num_alus;
1494*4882a593Smuzhiyun int num_statics;
1495*4882a593Smuzhiyun int cpu_ports;
1496*4882a593Smuzhiyun int port_cnt;
1497*4882a593Smuzhiyun bool phy_errata_9477;
1498*4882a593Smuzhiyun };
1499*4882a593Smuzhiyun
1500*4882a593Smuzhiyun static const struct ksz_chip_data ksz9477_switch_chips[] = {
1501*4882a593Smuzhiyun {
1502*4882a593Smuzhiyun .chip_id = 0x00947700,
1503*4882a593Smuzhiyun .dev_name = "KSZ9477",
1504*4882a593Smuzhiyun .num_vlans = 4096,
1505*4882a593Smuzhiyun .num_alus = 4096,
1506*4882a593Smuzhiyun .num_statics = 16,
1507*4882a593Smuzhiyun .cpu_ports = 0x7F, /* can be configured as cpu port */
1508*4882a593Smuzhiyun .port_cnt = 7, /* total physical port count */
1509*4882a593Smuzhiyun .phy_errata_9477 = true,
1510*4882a593Smuzhiyun },
1511*4882a593Smuzhiyun {
1512*4882a593Smuzhiyun .chip_id = 0x00989700,
1513*4882a593Smuzhiyun .dev_name = "KSZ9897",
1514*4882a593Smuzhiyun .num_vlans = 4096,
1515*4882a593Smuzhiyun .num_alus = 4096,
1516*4882a593Smuzhiyun .num_statics = 16,
1517*4882a593Smuzhiyun .cpu_ports = 0x7F, /* can be configured as cpu port */
1518*4882a593Smuzhiyun .port_cnt = 7, /* total physical port count */
1519*4882a593Smuzhiyun .phy_errata_9477 = true,
1520*4882a593Smuzhiyun },
1521*4882a593Smuzhiyun {
1522*4882a593Smuzhiyun .chip_id = 0x00989300,
1523*4882a593Smuzhiyun .dev_name = "KSZ9893",
1524*4882a593Smuzhiyun .num_vlans = 4096,
1525*4882a593Smuzhiyun .num_alus = 4096,
1526*4882a593Smuzhiyun .num_statics = 16,
1527*4882a593Smuzhiyun .cpu_ports = 0x07, /* can be configured as cpu port */
1528*4882a593Smuzhiyun .port_cnt = 3, /* total port count */
1529*4882a593Smuzhiyun },
1530*4882a593Smuzhiyun {
1531*4882a593Smuzhiyun .chip_id = 0x00956700,
1532*4882a593Smuzhiyun .dev_name = "KSZ9567",
1533*4882a593Smuzhiyun .num_vlans = 4096,
1534*4882a593Smuzhiyun .num_alus = 4096,
1535*4882a593Smuzhiyun .num_statics = 16,
1536*4882a593Smuzhiyun .cpu_ports = 0x7F, /* can be configured as cpu port */
1537*4882a593Smuzhiyun .port_cnt = 7, /* total physical port count */
1538*4882a593Smuzhiyun .phy_errata_9477 = true,
1539*4882a593Smuzhiyun },
1540*4882a593Smuzhiyun };
1541*4882a593Smuzhiyun
ksz9477_switch_init(struct ksz_device * dev)1542*4882a593Smuzhiyun static int ksz9477_switch_init(struct ksz_device *dev)
1543*4882a593Smuzhiyun {
1544*4882a593Smuzhiyun int i;
1545*4882a593Smuzhiyun
1546*4882a593Smuzhiyun dev->ds->ops = &ksz9477_switch_ops;
1547*4882a593Smuzhiyun
1548*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(ksz9477_switch_chips); i++) {
1549*4882a593Smuzhiyun const struct ksz_chip_data *chip = &ksz9477_switch_chips[i];
1550*4882a593Smuzhiyun
1551*4882a593Smuzhiyun if (dev->chip_id == chip->chip_id) {
1552*4882a593Smuzhiyun dev->name = chip->dev_name;
1553*4882a593Smuzhiyun dev->num_vlans = chip->num_vlans;
1554*4882a593Smuzhiyun dev->num_alus = chip->num_alus;
1555*4882a593Smuzhiyun dev->num_statics = chip->num_statics;
1556*4882a593Smuzhiyun dev->port_cnt = chip->port_cnt;
1557*4882a593Smuzhiyun dev->cpu_ports = chip->cpu_ports;
1558*4882a593Smuzhiyun dev->phy_errata_9477 = chip->phy_errata_9477;
1559*4882a593Smuzhiyun
1560*4882a593Smuzhiyun break;
1561*4882a593Smuzhiyun }
1562*4882a593Smuzhiyun }
1563*4882a593Smuzhiyun
1564*4882a593Smuzhiyun /* no switch found */
1565*4882a593Smuzhiyun if (!dev->port_cnt)
1566*4882a593Smuzhiyun return -ENODEV;
1567*4882a593Smuzhiyun
1568*4882a593Smuzhiyun dev->port_mask = (1 << dev->port_cnt) - 1;
1569*4882a593Smuzhiyun
1570*4882a593Smuzhiyun dev->reg_mib_cnt = SWITCH_COUNTER_NUM;
1571*4882a593Smuzhiyun dev->mib_cnt = TOTAL_SWITCH_COUNTER_NUM;
1572*4882a593Smuzhiyun
1573*4882a593Smuzhiyun i = dev->mib_port_cnt;
1574*4882a593Smuzhiyun dev->ports = devm_kzalloc(dev->dev, sizeof(struct ksz_port) * i,
1575*4882a593Smuzhiyun GFP_KERNEL);
1576*4882a593Smuzhiyun if (!dev->ports)
1577*4882a593Smuzhiyun return -ENOMEM;
1578*4882a593Smuzhiyun for (i = 0; i < dev->mib_port_cnt; i++) {
1579*4882a593Smuzhiyun mutex_init(&dev->ports[i].mib.cnt_mutex);
1580*4882a593Smuzhiyun dev->ports[i].mib.counters =
1581*4882a593Smuzhiyun devm_kzalloc(dev->dev,
1582*4882a593Smuzhiyun sizeof(u64) *
1583*4882a593Smuzhiyun (TOTAL_SWITCH_COUNTER_NUM + 1),
1584*4882a593Smuzhiyun GFP_KERNEL);
1585*4882a593Smuzhiyun if (!dev->ports[i].mib.counters)
1586*4882a593Smuzhiyun return -ENOMEM;
1587*4882a593Smuzhiyun }
1588*4882a593Smuzhiyun
1589*4882a593Smuzhiyun /* set the real number of ports */
1590*4882a593Smuzhiyun dev->ds->num_ports = dev->port_cnt;
1591*4882a593Smuzhiyun
1592*4882a593Smuzhiyun return 0;
1593*4882a593Smuzhiyun }
1594*4882a593Smuzhiyun
ksz9477_switch_exit(struct ksz_device * dev)1595*4882a593Smuzhiyun static void ksz9477_switch_exit(struct ksz_device *dev)
1596*4882a593Smuzhiyun {
1597*4882a593Smuzhiyun ksz9477_reset_switch(dev);
1598*4882a593Smuzhiyun }
1599*4882a593Smuzhiyun
1600*4882a593Smuzhiyun static const struct ksz_dev_ops ksz9477_dev_ops = {
1601*4882a593Smuzhiyun .get_port_addr = ksz9477_get_port_addr,
1602*4882a593Smuzhiyun .cfg_port_member = ksz9477_cfg_port_member,
1603*4882a593Smuzhiyun .flush_dyn_mac_table = ksz9477_flush_dyn_mac_table,
1604*4882a593Smuzhiyun .port_setup = ksz9477_port_setup,
1605*4882a593Smuzhiyun .r_mib_cnt = ksz9477_r_mib_cnt,
1606*4882a593Smuzhiyun .r_mib_pkt = ksz9477_r_mib_pkt,
1607*4882a593Smuzhiyun .freeze_mib = ksz9477_freeze_mib,
1608*4882a593Smuzhiyun .port_init_cnt = ksz9477_port_init_cnt,
1609*4882a593Smuzhiyun .shutdown = ksz9477_reset_switch,
1610*4882a593Smuzhiyun .detect = ksz9477_switch_detect,
1611*4882a593Smuzhiyun .init = ksz9477_switch_init,
1612*4882a593Smuzhiyun .exit = ksz9477_switch_exit,
1613*4882a593Smuzhiyun };
1614*4882a593Smuzhiyun
ksz9477_switch_register(struct ksz_device * dev)1615*4882a593Smuzhiyun int ksz9477_switch_register(struct ksz_device *dev)
1616*4882a593Smuzhiyun {
1617*4882a593Smuzhiyun int ret, i;
1618*4882a593Smuzhiyun struct phy_device *phydev;
1619*4882a593Smuzhiyun
1620*4882a593Smuzhiyun ret = ksz_switch_register(dev, &ksz9477_dev_ops);
1621*4882a593Smuzhiyun if (ret)
1622*4882a593Smuzhiyun return ret;
1623*4882a593Smuzhiyun
1624*4882a593Smuzhiyun for (i = 0; i < dev->phy_port_cnt; ++i) {
1625*4882a593Smuzhiyun if (!dsa_is_user_port(dev->ds, i))
1626*4882a593Smuzhiyun continue;
1627*4882a593Smuzhiyun
1628*4882a593Smuzhiyun phydev = dsa_to_port(dev->ds, i)->slave->phydev;
1629*4882a593Smuzhiyun
1630*4882a593Smuzhiyun /* The MAC actually cannot run in 1000 half-duplex mode. */
1631*4882a593Smuzhiyun phy_remove_link_mode(phydev,
1632*4882a593Smuzhiyun ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
1633*4882a593Smuzhiyun
1634*4882a593Smuzhiyun /* PHY does not support gigabit. */
1635*4882a593Smuzhiyun if (!(dev->features & GBIT_SUPPORT))
1636*4882a593Smuzhiyun phy_remove_link_mode(phydev,
1637*4882a593Smuzhiyun ETHTOOL_LINK_MODE_1000baseT_Full_BIT);
1638*4882a593Smuzhiyun }
1639*4882a593Smuzhiyun return ret;
1640*4882a593Smuzhiyun }
1641*4882a593Smuzhiyun EXPORT_SYMBOL(ksz9477_switch_register);
1642*4882a593Smuzhiyun
1643*4882a593Smuzhiyun MODULE_AUTHOR("Woojung Huh <Woojung.Huh@microchip.com>");
1644*4882a593Smuzhiyun MODULE_DESCRIPTION("Microchip KSZ9477 Series Switch DSA Driver");
1645*4882a593Smuzhiyun MODULE_LICENSE("GPL");
1646