Commit | Line | Data |
---|---|---|
c2e86691 TH |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* | |
3 | * Microchip KSZ9477 switch driver main logic | |
4 | * | |
42fc6a4c | 5 | * Copyright (C) 2017-2019 Microchip Technology Inc. |
c2e86691 TH |
6 | */ |
7 | ||
c2e86691 TH |
8 | #include <linux/kernel.h> |
9 | #include <linux/module.h> | |
7c6ff470 | 10 | #include <linux/iopoll.h> |
c2e86691 TH |
11 | #include <linux/platform_data/microchip-ksz.h> |
12 | #include <linux/phy.h> | |
c2e86691 | 13 | #include <linux/if_bridge.h> |
e18058ea | 14 | #include <linux/if_vlan.h> |
c2e86691 TH |
15 | #include <net/dsa.h> |
16 | #include <net/switchdev.h> | |
17 | ||
84bd1908 | 18 | #include "ksz9477_reg.h" |
7c6ff470 | 19 | #include "ksz_common.h" |
6ec23aaa | 20 | #include "ksz9477.h" |
c2e86691 | 21 | |
bafea01f MV |
22 | static void ksz_cfg(struct ksz_device *dev, u32 addr, u8 bits, bool set) |
23 | { | |
d4bcd99c | 24 | regmap_update_bits(dev->regmap[0], addr, bits, set ? bits : 0); |
bafea01f MV |
25 | } |
26 | ||
27 | static void ksz_port_cfg(struct ksz_device *dev, int port, int offset, u8 bits, | |
28 | bool set) | |
29 | { | |
d4bcd99c MV |
30 | regmap_update_bits(dev->regmap[0], PORT_CTRL_ADDR(port, offset), |
31 | bits, set ? bits : 0); | |
bafea01f MV |
32 | } |
33 | ||
c2e86691 TH |
34 | static void ksz9477_cfg32(struct ksz_device *dev, u32 addr, u32 bits, bool set) |
35 | { | |
d4bcd99c | 36 | regmap_update_bits(dev->regmap[2], addr, bits, set ? bits : 0); |
c2e86691 TH |
37 | } |
38 | ||
39 | static void ksz9477_port_cfg32(struct ksz_device *dev, int port, int offset, | |
40 | u32 bits, bool set) | |
41 | { | |
d4bcd99c MV |
42 | regmap_update_bits(dev->regmap[2], PORT_CTRL_ADDR(port, offset), |
43 | bits, set ? bits : 0); | |
c2e86691 TH |
44 | } |
45 | ||
6ec23aaa | 46 | int ksz9477_change_mtu(struct ksz_device *dev, int port, int mtu) |
e18058ea | 47 | { |
e18058ea OR |
48 | u16 frame_size, max_frame = 0; |
49 | int i; | |
50 | ||
51 | frame_size = mtu + VLAN_ETH_HLEN + ETH_FCS_LEN; | |
52 | ||
53 | /* Cache the per-port MTU setting */ | |
54 | dev->ports[port].max_frame = frame_size; | |
55 | ||
462d5250 | 56 | for (i = 0; i < dev->info->port_cnt; i++) |
e18058ea OR |
57 | max_frame = max(max_frame, dev->ports[i].max_frame); |
58 | ||
59 | return regmap_update_bits(dev->regmap[1], REG_SW_MTU__2, | |
60 | REG_SW_MTU_MASK, max_frame); | |
61 | } | |
62 | ||
6ec23aaa | 63 | int ksz9477_max_mtu(struct ksz_device *dev, int port) |
e18058ea OR |
64 | { |
65 | return KSZ9477_MAX_FRAME_SIZE - VLAN_ETH_HLEN - ETH_FCS_LEN; | |
66 | } | |
67 | ||
0f9c36e3 | 68 | static int ksz9477_wait_vlan_ctrl_ready(struct ksz_device *dev) |
c2e86691 | 69 | { |
0f9c36e3 | 70 | unsigned int val; |
c2e86691 | 71 | |
0f9c36e3 MV |
72 | return regmap_read_poll_timeout(dev->regmap[0], REG_SW_VLAN_CTRL, |
73 | val, !(val & VLAN_START), 10, 1000); | |
c2e86691 TH |
74 | } |
75 | ||
76 | static int ksz9477_get_vlan_table(struct ksz_device *dev, u16 vid, | |
77 | u32 *vlan_table) | |
78 | { | |
79 | int ret; | |
80 | ||
81 | mutex_lock(&dev->vlan_mutex); | |
82 | ||
83 | ksz_write16(dev, REG_SW_VLAN_ENTRY_INDEX__2, vid & VLAN_INDEX_M); | |
84 | ksz_write8(dev, REG_SW_VLAN_CTRL, VLAN_READ | VLAN_START); | |
85 | ||
86 | /* wait to be cleared */ | |
0f9c36e3 MV |
87 | ret = ksz9477_wait_vlan_ctrl_ready(dev); |
88 | if (ret) { | |
c2e86691 TH |
89 | dev_dbg(dev->dev, "Failed to read vlan table\n"); |
90 | goto exit; | |
91 | } | |
92 | ||
93 | ksz_read32(dev, REG_SW_VLAN_ENTRY__4, &vlan_table[0]); | |
94 | ksz_read32(dev, REG_SW_VLAN_ENTRY_UNTAG__4, &vlan_table[1]); | |
95 | ksz_read32(dev, REG_SW_VLAN_ENTRY_PORTS__4, &vlan_table[2]); | |
96 | ||
97 | ksz_write8(dev, REG_SW_VLAN_CTRL, 0); | |
98 | ||
99 | exit: | |
100 | mutex_unlock(&dev->vlan_mutex); | |
101 | ||
102 | return ret; | |
103 | } | |
104 | ||
105 | static int ksz9477_set_vlan_table(struct ksz_device *dev, u16 vid, | |
106 | u32 *vlan_table) | |
107 | { | |
108 | int ret; | |
109 | ||
110 | mutex_lock(&dev->vlan_mutex); | |
111 | ||
112 | ksz_write32(dev, REG_SW_VLAN_ENTRY__4, vlan_table[0]); | |
113 | ksz_write32(dev, REG_SW_VLAN_ENTRY_UNTAG__4, vlan_table[1]); | |
114 | ksz_write32(dev, REG_SW_VLAN_ENTRY_PORTS__4, vlan_table[2]); | |
115 | ||
116 | ksz_write16(dev, REG_SW_VLAN_ENTRY_INDEX__2, vid & VLAN_INDEX_M); | |
117 | ksz_write8(dev, REG_SW_VLAN_CTRL, VLAN_START | VLAN_WRITE); | |
118 | ||
119 | /* wait to be cleared */ | |
0f9c36e3 MV |
120 | ret = ksz9477_wait_vlan_ctrl_ready(dev); |
121 | if (ret) { | |
c2e86691 TH |
122 | dev_dbg(dev->dev, "Failed to write vlan table\n"); |
123 | goto exit; | |
124 | } | |
125 | ||
126 | ksz_write8(dev, REG_SW_VLAN_CTRL, 0); | |
127 | ||
128 | /* update vlan cache table */ | |
129 | dev->vlan_cache[vid].table[0] = vlan_table[0]; | |
130 | dev->vlan_cache[vid].table[1] = vlan_table[1]; | |
131 | dev->vlan_cache[vid].table[2] = vlan_table[2]; | |
132 | ||
133 | exit: | |
134 | mutex_unlock(&dev->vlan_mutex); | |
135 | ||
136 | return ret; | |
137 | } | |
138 | ||
139 | static void ksz9477_read_table(struct ksz_device *dev, u32 *table) | |
140 | { | |
141 | ksz_read32(dev, REG_SW_ALU_VAL_A, &table[0]); | |
142 | ksz_read32(dev, REG_SW_ALU_VAL_B, &table[1]); | |
143 | ksz_read32(dev, REG_SW_ALU_VAL_C, &table[2]); | |
144 | ksz_read32(dev, REG_SW_ALU_VAL_D, &table[3]); | |
145 | } | |
146 | ||
147 | static void ksz9477_write_table(struct ksz_device *dev, u32 *table) | |
148 | { | |
149 | ksz_write32(dev, REG_SW_ALU_VAL_A, table[0]); | |
150 | ksz_write32(dev, REG_SW_ALU_VAL_B, table[1]); | |
151 | ksz_write32(dev, REG_SW_ALU_VAL_C, table[2]); | |
152 | ksz_write32(dev, REG_SW_ALU_VAL_D, table[3]); | |
153 | } | |
154 | ||
ef534195 | 155 | static int ksz9477_wait_alu_ready(struct ksz_device *dev) |
c2e86691 | 156 | { |
ef534195 | 157 | unsigned int val; |
c2e86691 | 158 | |
ef534195 MV |
159 | return regmap_read_poll_timeout(dev->regmap[2], REG_SW_ALU_CTRL__4, |
160 | val, !(val & ALU_START), 10, 1000); | |
c2e86691 TH |
161 | } |
162 | ||
3371efbc | 163 | static int ksz9477_wait_alu_sta_ready(struct ksz_device *dev) |
c2e86691 | 164 | { |
3371efbc | 165 | unsigned int val; |
c2e86691 | 166 | |
3371efbc MV |
167 | return regmap_read_poll_timeout(dev->regmap[2], |
168 | REG_SW_ALU_STAT_CTRL__4, | |
169 | val, !(val & ALU_STAT_START), | |
170 | 10, 1000); | |
c2e86691 TH |
171 | } |
172 | ||
6ec23aaa | 173 | int ksz9477_reset_switch(struct ksz_device *dev) |
c2e86691 TH |
174 | { |
175 | u8 data8; | |
c2e86691 TH |
176 | u32 data32; |
177 | ||
178 | /* reset switch */ | |
179 | ksz_cfg(dev, REG_SW_OPERATION, SW_RESET, true); | |
180 | ||
181 | /* turn off SPI DO Edge select */ | |
ee353e45 MV |
182 | regmap_update_bits(dev->regmap[0], REG_SW_GLOBAL_SERIAL_CTRL_0, |
183 | SPI_AUTO_EDGE_DETECTION, 0); | |
c2e86691 TH |
184 | |
185 | /* default configuration */ | |
186 | ksz_read8(dev, REG_SW_LUE_CTRL_1, &data8); | |
187 | data8 = SW_AGING_ENABLE | SW_LINK_AUTO_AGING | | |
188 | SW_SRC_ADDR_FILTER | SW_FLUSH_STP_TABLE | SW_FLUSH_MSTP_TABLE; | |
189 | ksz_write8(dev, REG_SW_LUE_CTRL_1, data8); | |
190 | ||
191 | /* disable interrupts */ | |
192 | ksz_write32(dev, REG_SW_INT_MASK__4, SWITCH_INT_MASK); | |
193 | ksz_write32(dev, REG_SW_PORT_INT_MASK__4, 0x7F); | |
194 | ksz_read32(dev, REG_SW_PORT_INT_STATUS__4, &data32); | |
195 | ||
48bf8b8a RH |
196 | data8 = SW_ENABLE_REFCLKO; |
197 | if (dev->synclko_disable) | |
198 | data8 = 0; | |
199 | else if (dev->synclko_125) | |
200 | data8 = SW_ENABLE_REFCLKO | SW_REFCLKO_IS_125MHZ; | |
201 | ksz_write8(dev, REG_SW_GLOBAL_OUTPUT_CTRL__1, data8); | |
79c8bd15 | 202 | |
c2e86691 TH |
203 | return 0; |
204 | } | |
205 | ||
6ec23aaa | 206 | void ksz9477_r_mib_cnt(struct ksz_device *dev, int port, u16 addr, u64 *cnt) |
7c6ff470 | 207 | { |
7c6ff470 | 208 | struct ksz_port *p = &dev->ports[port]; |
1c1eb580 | 209 | unsigned int val; |
7c6ff470 TH |
210 | u32 data; |
211 | int ret; | |
212 | ||
213 | /* retain the flush/freeze bit */ | |
214 | data = p->freeze ? MIB_COUNTER_FLUSH_FREEZE : 0; | |
215 | data |= MIB_COUNTER_READ; | |
216 | data |= (addr << MIB_COUNTER_INDEX_S); | |
217 | ksz_pwrite32(dev, port, REG_PORT_MIB_CTRL_STAT__4, data); | |
218 | ||
1c1eb580 MV |
219 | ret = regmap_read_poll_timeout(dev->regmap[2], |
220 | PORT_CTRL_ADDR(port, REG_PORT_MIB_CTRL_STAT__4), | |
221 | val, !(val & MIB_COUNTER_READ), 10, 1000); | |
7c6ff470 | 222 | /* failed to read MIB. get out of loop */ |
1c1eb580 | 223 | if (ret) { |
7c6ff470 TH |
224 | dev_dbg(dev->dev, "Failed to get MIB\n"); |
225 | return; | |
226 | } | |
227 | ||
228 | /* count resets upon read */ | |
229 | ksz_pread32(dev, port, REG_PORT_MIB_DATA, &data); | |
230 | *cnt += data; | |
231 | } | |
232 | ||
6ec23aaa AR |
233 | void ksz9477_r_mib_pkt(struct ksz_device *dev, int port, u16 addr, |
234 | u64 *dropped, u64 *cnt) | |
7c6ff470 | 235 | { |
a530e6f2 | 236 | addr = dev->info->mib_names[addr].index; |
7c6ff470 TH |
237 | ksz9477_r_mib_cnt(dev, port, addr, cnt); |
238 | } | |
239 | ||
6ec23aaa | 240 | void ksz9477_freeze_mib(struct ksz_device *dev, int port, bool freeze) |
7c6ff470 TH |
241 | { |
242 | u32 val = freeze ? MIB_COUNTER_FLUSH_FREEZE : 0; | |
243 | struct ksz_port *p = &dev->ports[port]; | |
244 | ||
245 | /* enable/disable the port for flush/freeze function */ | |
246 | mutex_lock(&p->mib.cnt_mutex); | |
247 | ksz_pwrite32(dev, port, REG_PORT_MIB_CTRL_STAT__4, val); | |
248 | ||
249 | /* used by MIB counter reading code to know freeze is enabled */ | |
250 | p->freeze = freeze; | |
251 | mutex_unlock(&p->mib.cnt_mutex); | |
252 | } | |
253 | ||
6ec23aaa | 254 | void ksz9477_port_init_cnt(struct ksz_device *dev, int port) |
7c6ff470 TH |
255 | { |
256 | struct ksz_port_mib *mib = &dev->ports[port].mib; | |
257 | ||
258 | /* flush all enabled port MIB counters */ | |
259 | mutex_lock(&mib->cnt_mutex); | |
260 | ksz_pwrite32(dev, port, REG_PORT_MIB_CTRL_STAT__4, | |
261 | MIB_COUNTER_FLUSH_FREEZE); | |
262 | ksz_write8(dev, REG_SW_MAC_CTRL_6, SW_MIB_COUNTER_FLUSH); | |
263 | ksz_pwrite32(dev, port, REG_PORT_MIB_CTRL_STAT__4, 0); | |
264 | mutex_unlock(&mib->cnt_mutex); | |
7c6ff470 TH |
265 | } |
266 | ||
d7539fc2 OR |
267 | static void ksz9477_r_phy_quirks(struct ksz_device *dev, u16 addr, u16 reg, |
268 | u16 *data) | |
269 | { | |
270 | /* KSZ8563R do not have extended registers but BMSR_ESTATEN and | |
271 | * BMSR_ERCAP bits are set. | |
272 | */ | |
273 | if (dev->chip_id == KSZ8563_CHIP_ID && reg == MII_BMSR) | |
274 | *data &= ~(BMSR_ESTATEN | BMSR_ERCAP); | |
275 | } | |
276 | ||
6ec23aaa | 277 | void ksz9477_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data) |
c2e86691 | 278 | { |
c2e86691 TH |
279 | u16 val = 0xffff; |
280 | ||
281 | /* No real PHY after this. Simulate the PHY. | |
282 | * A fixed PHY can be setup in the device tree, but this function is | |
283 | * still called for that port during initialization. | |
284 | * For RGMII PHY there is no way to access it so the fixed PHY should | |
285 | * be used. For SGMII PHY the supporting code will be added later. | |
286 | */ | |
287 | if (addr >= dev->phy_port_cnt) { | |
288 | struct ksz_port *p = &dev->ports[addr]; | |
289 | ||
290 | switch (reg) { | |
291 | case MII_BMCR: | |
292 | val = 0x1140; | |
293 | break; | |
294 | case MII_BMSR: | |
295 | val = 0x796d; | |
296 | break; | |
297 | case MII_PHYSID1: | |
298 | val = 0x0022; | |
299 | break; | |
300 | case MII_PHYSID2: | |
301 | val = 0x1631; | |
302 | break; | |
303 | case MII_ADVERTISE: | |
304 | val = 0x05e1; | |
305 | break; | |
306 | case MII_LPA: | |
307 | val = 0xc5e1; | |
308 | break; | |
309 | case MII_CTRL1000: | |
310 | val = 0x0700; | |
311 | break; | |
312 | case MII_STAT1000: | |
313 | if (p->phydev.speed == SPEED_1000) | |
314 | val = 0x3800; | |
315 | else | |
316 | val = 0; | |
317 | break; | |
318 | } | |
319 | } else { | |
320 | ksz_pread16(dev, addr, 0x100 + (reg << 1), &val); | |
d7539fc2 | 321 | ksz9477_r_phy_quirks(dev, addr, reg, &val); |
c2e86691 TH |
322 | } |
323 | ||
930e5790 | 324 | *data = val; |
c2e86691 TH |
325 | } |
326 | ||
6ec23aaa | 327 | void ksz9477_w_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 val) |
c2e86691 | 328 | { |
c2e86691 TH |
329 | /* No real PHY after this. */ |
330 | if (addr >= dev->phy_port_cnt) | |
930e5790 | 331 | return; |
8c29bebb TH |
332 | |
333 | /* No gigabit support. Do not write to this register. */ | |
505bf320 | 334 | if (!dev->info->gbit_capable[addr] && reg == MII_CTRL1000) |
930e5790 | 335 | return; |
c2e86691 | 336 | |
930e5790 | 337 | ksz_pwrite16(dev, addr, 0x100 + (reg << 1), val); |
c2e86691 TH |
338 | } |
339 | ||
6ec23aaa | 340 | void ksz9477_cfg_port_member(struct ksz_device *dev, int port, u8 member) |
c2e86691 TH |
341 | { |
342 | ksz_pwrite32(dev, port, REG_PORT_VLAN_MEMBERSHIP__4, member); | |
c2e86691 TH |
343 | } |
344 | ||
6ec23aaa | 345 | void ksz9477_flush_dyn_mac_table(struct ksz_device *dev, int port) |
c2e86691 | 346 | { |
6877102f | 347 | const u16 *regs = dev->info->regs; |
c2e86691 TH |
348 | u8 data; |
349 | ||
ee353e45 MV |
350 | regmap_update_bits(dev->regmap[0], REG_SW_LUE_CTRL_2, |
351 | SW_FLUSH_OPTION_M << SW_FLUSH_OPTION_S, | |
352 | SW_FLUSH_OPTION_DYN_MAC << SW_FLUSH_OPTION_S); | |
353 | ||
462d5250 | 354 | if (port < dev->info->port_cnt) { |
c2e86691 | 355 | /* flush individual port */ |
6877102f | 356 | ksz_pread8(dev, port, regs[P_STP_CTRL], &data); |
c2e86691 | 357 | if (!(data & PORT_LEARN_DISABLE)) |
6877102f | 358 | ksz_pwrite8(dev, port, regs[P_STP_CTRL], |
c2e86691 TH |
359 | data | PORT_LEARN_DISABLE); |
360 | ksz_cfg(dev, S_FLUSH_TABLE_CTRL, SW_FLUSH_DYN_MAC_TABLE, true); | |
6877102f | 361 | ksz_pwrite8(dev, port, regs[P_STP_CTRL], data); |
c2e86691 TH |
362 | } else { |
363 | /* flush all */ | |
364 | ksz_cfg(dev, S_FLUSH_TABLE_CTRL, SW_FLUSH_STP_TABLE, true); | |
365 | } | |
366 | } | |
367 | ||
6ec23aaa AR |
368 | int ksz9477_port_vlan_filtering(struct ksz_device *dev, int port, |
369 | bool flag, struct netlink_ext_ack *extack) | |
c2e86691 | 370 | { |
c2e86691 TH |
371 | if (flag) { |
372 | ksz_port_cfg(dev, port, REG_PORT_LUE_CTRL, | |
373 | PORT_VLAN_LOOKUP_VID_0, true); | |
c2e86691 TH |
374 | ksz_cfg(dev, REG_SW_LUE_CTRL_0, SW_VLAN_ENABLE, true); |
375 | } else { | |
376 | ksz_cfg(dev, REG_SW_LUE_CTRL_0, SW_VLAN_ENABLE, false); | |
c2e86691 TH |
377 | ksz_port_cfg(dev, port, REG_PORT_LUE_CTRL, |
378 | PORT_VLAN_LOOKUP_VID_0, false); | |
379 | } | |
380 | ||
381 | return 0; | |
382 | } | |
383 | ||
6ec23aaa AR |
384 | int ksz9477_port_vlan_add(struct ksz_device *dev, int port, |
385 | const struct switchdev_obj_port_vlan *vlan, | |
386 | struct netlink_ext_ack *extack) | |
c2e86691 | 387 | { |
c2e86691 | 388 | u32 vlan_table[3]; |
c2e86691 | 389 | bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED; |
1958d581 | 390 | int err; |
c2e86691 | 391 | |
1958d581 VO |
392 | err = ksz9477_get_vlan_table(dev, vlan->vid, vlan_table); |
393 | if (err) { | |
31046a5f | 394 | NL_SET_ERR_MSG_MOD(extack, "Failed to get vlan table"); |
1958d581 | 395 | return err; |
b7a9e0da | 396 | } |
c2e86691 | 397 | |
b7a9e0da VO |
398 | vlan_table[0] = VLAN_VALID | (vlan->vid & VLAN_FID_M); |
399 | if (untagged) | |
400 | vlan_table[1] |= BIT(port); | |
401 | else | |
402 | vlan_table[1] &= ~BIT(port); | |
403 | vlan_table[1] &= ~(BIT(dev->cpu_port)); | |
c2e86691 | 404 | |
b7a9e0da | 405 | vlan_table[2] |= BIT(port) | BIT(dev->cpu_port); |
c2e86691 | 406 | |
1958d581 VO |
407 | err = ksz9477_set_vlan_table(dev, vlan->vid, vlan_table); |
408 | if (err) { | |
31046a5f | 409 | NL_SET_ERR_MSG_MOD(extack, "Failed to set vlan table"); |
1958d581 | 410 | return err; |
c2e86691 | 411 | } |
b7a9e0da VO |
412 | |
413 | /* change PVID */ | |
414 | if (vlan->flags & BRIDGE_VLAN_INFO_PVID) | |
415 | ksz_pwrite16(dev, port, REG_PORT_DEFAULT_VID, vlan->vid); | |
1958d581 VO |
416 | |
417 | return 0; | |
c2e86691 TH |
418 | } |
419 | ||
6ec23aaa AR |
420 | int ksz9477_port_vlan_del(struct ksz_device *dev, int port, |
421 | const struct switchdev_obj_port_vlan *vlan) | |
c2e86691 | 422 | { |
c2e86691 TH |
423 | bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED; |
424 | u32 vlan_table[3]; | |
c2e86691 TH |
425 | u16 pvid; |
426 | ||
427 | ksz_pread16(dev, port, REG_PORT_DEFAULT_VID, &pvid); | |
428 | pvid = pvid & 0xFFF; | |
429 | ||
b7a9e0da VO |
430 | if (ksz9477_get_vlan_table(dev, vlan->vid, vlan_table)) { |
431 | dev_dbg(dev->dev, "Failed to get vlan table\n"); | |
432 | return -ETIMEDOUT; | |
433 | } | |
c2e86691 | 434 | |
b7a9e0da | 435 | vlan_table[2] &= ~BIT(port); |
c2e86691 | 436 | |
b7a9e0da VO |
437 | if (pvid == vlan->vid) |
438 | pvid = 1; | |
c2e86691 | 439 | |
b7a9e0da VO |
440 | if (untagged) |
441 | vlan_table[1] &= ~BIT(port); | |
c2e86691 | 442 | |
b7a9e0da VO |
443 | if (ksz9477_set_vlan_table(dev, vlan->vid, vlan_table)) { |
444 | dev_dbg(dev->dev, "Failed to set vlan table\n"); | |
445 | return -ETIMEDOUT; | |
c2e86691 TH |
446 | } |
447 | ||
448 | ksz_pwrite16(dev, port, REG_PORT_DEFAULT_VID, pvid); | |
449 | ||
450 | return 0; | |
451 | } | |
452 | ||
6ec23aaa AR |
453 | int ksz9477_fdb_add(struct ksz_device *dev, int port, |
454 | const unsigned char *addr, u16 vid, struct dsa_db db) | |
c2e86691 | 455 | { |
c2e86691 TH |
456 | u32 alu_table[4]; |
457 | u32 data; | |
458 | int ret = 0; | |
459 | ||
460 | mutex_lock(&dev->alu_mutex); | |
461 | ||
462 | /* find any entry with mac & vid */ | |
463 | data = vid << ALU_FID_INDEX_S; | |
464 | data |= ((addr[0] << 8) | addr[1]); | |
465 | ksz_write32(dev, REG_SW_ALU_INDEX_0, data); | |
466 | ||
467 | data = ((addr[2] << 24) | (addr[3] << 16)); | |
468 | data |= ((addr[4] << 8) | addr[5]); | |
469 | ksz_write32(dev, REG_SW_ALU_INDEX_1, data); | |
470 | ||
471 | /* start read operation */ | |
472 | ksz_write32(dev, REG_SW_ALU_CTRL__4, ALU_READ | ALU_START); | |
473 | ||
474 | /* wait to be finished */ | |
ef534195 MV |
475 | ret = ksz9477_wait_alu_ready(dev); |
476 | if (ret) { | |
c2e86691 TH |
477 | dev_dbg(dev->dev, "Failed to read ALU\n"); |
478 | goto exit; | |
479 | } | |
480 | ||
481 | /* read ALU entry */ | |
482 | ksz9477_read_table(dev, alu_table); | |
483 | ||
484 | /* update ALU entry */ | |
485 | alu_table[0] = ALU_V_STATIC_VALID; | |
486 | alu_table[1] |= BIT(port); | |
487 | if (vid) | |
488 | alu_table[1] |= ALU_V_USE_FID; | |
489 | alu_table[2] = (vid << ALU_V_FID_S); | |
490 | alu_table[2] |= ((addr[0] << 8) | addr[1]); | |
491 | alu_table[3] = ((addr[2] << 24) | (addr[3] << 16)); | |
492 | alu_table[3] |= ((addr[4] << 8) | addr[5]); | |
493 | ||
494 | ksz9477_write_table(dev, alu_table); | |
495 | ||
496 | ksz_write32(dev, REG_SW_ALU_CTRL__4, ALU_WRITE | ALU_START); | |
497 | ||
498 | /* wait to be finished */ | |
ef534195 MV |
499 | ret = ksz9477_wait_alu_ready(dev); |
500 | if (ret) | |
c2e86691 TH |
501 | dev_dbg(dev->dev, "Failed to write ALU\n"); |
502 | ||
503 | exit: | |
504 | mutex_unlock(&dev->alu_mutex); | |
505 | ||
506 | return ret; | |
507 | } | |
508 | ||
6ec23aaa AR |
509 | int ksz9477_fdb_del(struct ksz_device *dev, int port, |
510 | const unsigned char *addr, u16 vid, struct dsa_db db) | |
c2e86691 | 511 | { |
c2e86691 TH |
512 | u32 alu_table[4]; |
513 | u32 data; | |
514 | int ret = 0; | |
515 | ||
516 | mutex_lock(&dev->alu_mutex); | |
517 | ||
518 | /* read any entry with mac & vid */ | |
519 | data = vid << ALU_FID_INDEX_S; | |
520 | data |= ((addr[0] << 8) | addr[1]); | |
521 | ksz_write32(dev, REG_SW_ALU_INDEX_0, data); | |
522 | ||
523 | data = ((addr[2] << 24) | (addr[3] << 16)); | |
524 | data |= ((addr[4] << 8) | addr[5]); | |
525 | ksz_write32(dev, REG_SW_ALU_INDEX_1, data); | |
526 | ||
527 | /* start read operation */ | |
528 | ksz_write32(dev, REG_SW_ALU_CTRL__4, ALU_READ | ALU_START); | |
529 | ||
530 | /* wait to be finished */ | |
ef534195 MV |
531 | ret = ksz9477_wait_alu_ready(dev); |
532 | if (ret) { | |
c2e86691 TH |
533 | dev_dbg(dev->dev, "Failed to read ALU\n"); |
534 | goto exit; | |
535 | } | |
536 | ||
537 | ksz_read32(dev, REG_SW_ALU_VAL_A, &alu_table[0]); | |
538 | if (alu_table[0] & ALU_V_STATIC_VALID) { | |
539 | ksz_read32(dev, REG_SW_ALU_VAL_B, &alu_table[1]); | |
540 | ksz_read32(dev, REG_SW_ALU_VAL_C, &alu_table[2]); | |
541 | ksz_read32(dev, REG_SW_ALU_VAL_D, &alu_table[3]); | |
542 | ||
543 | /* clear forwarding port */ | |
544 | alu_table[2] &= ~BIT(port); | |
545 | ||
546 | /* if there is no port to forward, clear table */ | |
547 | if ((alu_table[2] & ALU_V_PORT_MAP) == 0) { | |
548 | alu_table[0] = 0; | |
549 | alu_table[1] = 0; | |
550 | alu_table[2] = 0; | |
551 | alu_table[3] = 0; | |
552 | } | |
553 | } else { | |
554 | alu_table[0] = 0; | |
555 | alu_table[1] = 0; | |
556 | alu_table[2] = 0; | |
557 | alu_table[3] = 0; | |
558 | } | |
559 | ||
560 | ksz9477_write_table(dev, alu_table); | |
561 | ||
562 | ksz_write32(dev, REG_SW_ALU_CTRL__4, ALU_WRITE | ALU_START); | |
563 | ||
564 | /* wait to be finished */ | |
ef534195 MV |
565 | ret = ksz9477_wait_alu_ready(dev); |
566 | if (ret) | |
c2e86691 TH |
567 | dev_dbg(dev->dev, "Failed to write ALU\n"); |
568 | ||
569 | exit: | |
570 | mutex_unlock(&dev->alu_mutex); | |
571 | ||
572 | return ret; | |
573 | } | |
574 | ||
575 | static void ksz9477_convert_alu(struct alu_struct *alu, u32 *alu_table) | |
576 | { | |
577 | alu->is_static = !!(alu_table[0] & ALU_V_STATIC_VALID); | |
578 | alu->is_src_filter = !!(alu_table[0] & ALU_V_SRC_FILTER); | |
579 | alu->is_dst_filter = !!(alu_table[0] & ALU_V_DST_FILTER); | |
580 | alu->prio_age = (alu_table[0] >> ALU_V_PRIO_AGE_CNT_S) & | |
581 | ALU_V_PRIO_AGE_CNT_M; | |
582 | alu->mstp = alu_table[0] & ALU_V_MSTP_M; | |
583 | ||
584 | alu->is_override = !!(alu_table[1] & ALU_V_OVERRIDE); | |
585 | alu->is_use_fid = !!(alu_table[1] & ALU_V_USE_FID); | |
586 | alu->port_forward = alu_table[1] & ALU_V_PORT_MAP; | |
587 | ||
588 | alu->fid = (alu_table[2] >> ALU_V_FID_S) & ALU_V_FID_M; | |
589 | ||
590 | alu->mac[0] = (alu_table[2] >> 8) & 0xFF; | |
591 | alu->mac[1] = alu_table[2] & 0xFF; | |
592 | alu->mac[2] = (alu_table[3] >> 24) & 0xFF; | |
593 | alu->mac[3] = (alu_table[3] >> 16) & 0xFF; | |
594 | alu->mac[4] = (alu_table[3] >> 8) & 0xFF; | |
595 | alu->mac[5] = alu_table[3] & 0xFF; | |
596 | } | |
597 | ||
6ec23aaa AR |
598 | int ksz9477_fdb_dump(struct ksz_device *dev, int port, |
599 | dsa_fdb_dump_cb_t *cb, void *data) | |
c2e86691 | 600 | { |
c2e86691 TH |
601 | int ret = 0; |
602 | u32 ksz_data; | |
603 | u32 alu_table[4]; | |
604 | struct alu_struct alu; | |
605 | int timeout; | |
606 | ||
607 | mutex_lock(&dev->alu_mutex); | |
608 | ||
609 | /* start ALU search */ | |
610 | ksz_write32(dev, REG_SW_ALU_CTRL__4, ALU_START | ALU_SEARCH); | |
611 | ||
612 | do { | |
613 | timeout = 1000; | |
614 | do { | |
615 | ksz_read32(dev, REG_SW_ALU_CTRL__4, &ksz_data); | |
616 | if ((ksz_data & ALU_VALID) || !(ksz_data & ALU_START)) | |
617 | break; | |
618 | usleep_range(1, 10); | |
619 | } while (timeout-- > 0); | |
620 | ||
621 | if (!timeout) { | |
622 | dev_dbg(dev->dev, "Failed to search ALU\n"); | |
623 | ret = -ETIMEDOUT; | |
624 | goto exit; | |
625 | } | |
626 | ||
36c0d935 AR |
627 | if (!(ksz_data & ALU_VALID)) |
628 | continue; | |
629 | ||
c2e86691 TH |
630 | /* read ALU table */ |
631 | ksz9477_read_table(dev, alu_table); | |
632 | ||
633 | ksz9477_convert_alu(&alu, alu_table); | |
634 | ||
635 | if (alu.port_forward & BIT(port)) { | |
636 | ret = cb(alu.mac, alu.fid, alu.is_static, data); | |
637 | if (ret) | |
638 | goto exit; | |
639 | } | |
640 | } while (ksz_data & ALU_START); | |
641 | ||
642 | exit: | |
643 | ||
644 | /* stop ALU search */ | |
645 | ksz_write32(dev, REG_SW_ALU_CTRL__4, 0); | |
646 | ||
647 | mutex_unlock(&dev->alu_mutex); | |
648 | ||
649 | return ret; | |
650 | } | |
651 | ||
6ec23aaa AR |
652 | int ksz9477_mdb_add(struct ksz_device *dev, int port, |
653 | const struct switchdev_obj_port_mdb *mdb, struct dsa_db db) | |
c2e86691 | 654 | { |
c2e86691 | 655 | u32 static_table[4]; |
457c182a AR |
656 | const u8 *shifts; |
657 | const u32 *masks; | |
c2e86691 TH |
658 | u32 data; |
659 | int index; | |
660 | u32 mac_hi, mac_lo; | |
a52b2da7 | 661 | int err = 0; |
c2e86691 | 662 | |
457c182a AR |
663 | shifts = dev->info->shifts; |
664 | masks = dev->info->masks; | |
665 | ||
c2e86691 TH |
666 | mac_hi = ((mdb->addr[0] << 8) | mdb->addr[1]); |
667 | mac_lo = ((mdb->addr[2] << 24) | (mdb->addr[3] << 16)); | |
668 | mac_lo |= ((mdb->addr[4] << 8) | mdb->addr[5]); | |
669 | ||
670 | mutex_lock(&dev->alu_mutex); | |
671 | ||
462d5250 | 672 | for (index = 0; index < dev->info->num_statics; index++) { |
c2e86691 | 673 | /* find empty slot first */ |
457c182a AR |
674 | data = (index << shifts[ALU_STAT_INDEX]) | |
675 | masks[ALU_STAT_READ] | ALU_STAT_START; | |
c2e86691 TH |
676 | ksz_write32(dev, REG_SW_ALU_STAT_CTRL__4, data); |
677 | ||
678 | /* wait to be finished */ | |
a52b2da7 VO |
679 | err = ksz9477_wait_alu_sta_ready(dev); |
680 | if (err) { | |
c2e86691 TH |
681 | dev_dbg(dev->dev, "Failed to read ALU STATIC\n"); |
682 | goto exit; | |
683 | } | |
684 | ||
685 | /* read ALU static table */ | |
686 | ksz9477_read_table(dev, static_table); | |
687 | ||
688 | if (static_table[0] & ALU_V_STATIC_VALID) { | |
689 | /* check this has same vid & mac address */ | |
690 | if (((static_table[2] >> ALU_V_FID_S) == mdb->vid) && | |
691 | ((static_table[2] & ALU_V_MAC_ADDR_HI) == mac_hi) && | |
692 | static_table[3] == mac_lo) { | |
693 | /* found matching one */ | |
694 | break; | |
695 | } | |
696 | } else { | |
697 | /* found empty one */ | |
698 | break; | |
699 | } | |
700 | } | |
701 | ||
702 | /* no available entry */ | |
462d5250 | 703 | if (index == dev->info->num_statics) { |
a52b2da7 | 704 | err = -ENOSPC; |
c2e86691 | 705 | goto exit; |
a52b2da7 | 706 | } |
c2e86691 TH |
707 | |
708 | /* add entry */ | |
709 | static_table[0] = ALU_V_STATIC_VALID; | |
710 | static_table[1] |= BIT(port); | |
711 | if (mdb->vid) | |
712 | static_table[1] |= ALU_V_USE_FID; | |
713 | static_table[2] = (mdb->vid << ALU_V_FID_S); | |
714 | static_table[2] |= mac_hi; | |
715 | static_table[3] = mac_lo; | |
716 | ||
717 | ksz9477_write_table(dev, static_table); | |
718 | ||
457c182a | 719 | data = (index << shifts[ALU_STAT_INDEX]) | ALU_STAT_START; |
c2e86691 TH |
720 | ksz_write32(dev, REG_SW_ALU_STAT_CTRL__4, data); |
721 | ||
722 | /* wait to be finished */ | |
3371efbc | 723 | if (ksz9477_wait_alu_sta_ready(dev)) |
c2e86691 TH |
724 | dev_dbg(dev->dev, "Failed to read ALU STATIC\n"); |
725 | ||
726 | exit: | |
727 | mutex_unlock(&dev->alu_mutex); | |
a52b2da7 | 728 | return err; |
c2e86691 TH |
729 | } |
730 | ||
6ec23aaa AR |
731 | int ksz9477_mdb_del(struct ksz_device *dev, int port, |
732 | const struct switchdev_obj_port_mdb *mdb, struct dsa_db db) | |
c2e86691 | 733 | { |
c2e86691 | 734 | u32 static_table[4]; |
457c182a AR |
735 | const u8 *shifts; |
736 | const u32 *masks; | |
c2e86691 TH |
737 | u32 data; |
738 | int index; | |
739 | int ret = 0; | |
740 | u32 mac_hi, mac_lo; | |
741 | ||
457c182a AR |
742 | shifts = dev->info->shifts; |
743 | masks = dev->info->masks; | |
744 | ||
c2e86691 TH |
745 | mac_hi = ((mdb->addr[0] << 8) | mdb->addr[1]); |
746 | mac_lo = ((mdb->addr[2] << 24) | (mdb->addr[3] << 16)); | |
747 | mac_lo |= ((mdb->addr[4] << 8) | mdb->addr[5]); | |
748 | ||
749 | mutex_lock(&dev->alu_mutex); | |
750 | ||
462d5250 | 751 | for (index = 0; index < dev->info->num_statics; index++) { |
c2e86691 | 752 | /* find empty slot first */ |
457c182a AR |
753 | data = (index << shifts[ALU_STAT_INDEX]) | |
754 | masks[ALU_STAT_READ] | ALU_STAT_START; | |
c2e86691 TH |
755 | ksz_write32(dev, REG_SW_ALU_STAT_CTRL__4, data); |
756 | ||
757 | /* wait to be finished */ | |
3371efbc MV |
758 | ret = ksz9477_wait_alu_sta_ready(dev); |
759 | if (ret) { | |
c2e86691 TH |
760 | dev_dbg(dev->dev, "Failed to read ALU STATIC\n"); |
761 | goto exit; | |
762 | } | |
763 | ||
764 | /* read ALU static table */ | |
765 | ksz9477_read_table(dev, static_table); | |
766 | ||
767 | if (static_table[0] & ALU_V_STATIC_VALID) { | |
768 | /* check this has same vid & mac address */ | |
769 | ||
770 | if (((static_table[2] >> ALU_V_FID_S) == mdb->vid) && | |
771 | ((static_table[2] & ALU_V_MAC_ADDR_HI) == mac_hi) && | |
772 | static_table[3] == mac_lo) { | |
773 | /* found matching one */ | |
774 | break; | |
775 | } | |
776 | } | |
777 | } | |
778 | ||
779 | /* no available entry */ | |
462d5250 | 780 | if (index == dev->info->num_statics) |
c2e86691 TH |
781 | goto exit; |
782 | ||
783 | /* clear port */ | |
784 | static_table[1] &= ~BIT(port); | |
785 | ||
786 | if ((static_table[1] & ALU_V_PORT_MAP) == 0) { | |
787 | /* delete entry */ | |
788 | static_table[0] = 0; | |
789 | static_table[1] = 0; | |
790 | static_table[2] = 0; | |
791 | static_table[3] = 0; | |
792 | } | |
793 | ||
794 | ksz9477_write_table(dev, static_table); | |
795 | ||
457c182a | 796 | data = (index << shifts[ALU_STAT_INDEX]) | ALU_STAT_START; |
c2e86691 TH |
797 | ksz_write32(dev, REG_SW_ALU_STAT_CTRL__4, data); |
798 | ||
799 | /* wait to be finished */ | |
3371efbc MV |
800 | ret = ksz9477_wait_alu_sta_ready(dev); |
801 | if (ret) | |
c2e86691 TH |
802 | dev_dbg(dev->dev, "Failed to read ALU STATIC\n"); |
803 | ||
804 | exit: | |
805 | mutex_unlock(&dev->alu_mutex); | |
806 | ||
807 | return ret; | |
808 | } | |
809 | ||
6ec23aaa AR |
810 | int ksz9477_port_mirror_add(struct ksz_device *dev, int port, |
811 | struct dsa_mall_mirror_tc_entry *mirror, | |
812 | bool ingress, struct netlink_ext_ack *extack) | |
c2e86691 | 813 | { |
fee34dd1 AR |
814 | u8 data; |
815 | int p; | |
816 | ||
817 | /* Limit to one sniffer port | |
818 | * Check if any of the port is already set for sniffing | |
819 | * If yes, instruct the user to remove the previous entry & exit | |
820 | */ | |
462d5250 | 821 | for (p = 0; p < dev->info->port_cnt; p++) { |
fee34dd1 AR |
822 | /* Skip the current sniffing port */ |
823 | if (p == mirror->to_local_port) | |
824 | continue; | |
825 | ||
826 | ksz_pread8(dev, p, P_MIRROR_CTRL, &data); | |
827 | ||
828 | if (data & PORT_MIRROR_SNIFFER) { | |
829 | NL_SET_ERR_MSG_MOD(extack, | |
830 | "Sniffer port is already configured, delete existing rules & retry"); | |
831 | return -EBUSY; | |
832 | } | |
833 | } | |
c2e86691 TH |
834 | |
835 | if (ingress) | |
836 | ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_RX, true); | |
837 | else | |
838 | ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_TX, true); | |
839 | ||
c2e86691 TH |
840 | /* configure mirror port */ |
841 | ksz_port_cfg(dev, mirror->to_local_port, P_MIRROR_CTRL, | |
842 | PORT_MIRROR_SNIFFER, true); | |
843 | ||
844 | ksz_cfg(dev, S_MIRROR_CTRL, SW_MIRROR_RX_TX, false); | |
845 | ||
846 | return 0; | |
847 | } | |
848 | ||
6ec23aaa AR |
849 | void ksz9477_port_mirror_del(struct ksz_device *dev, int port, |
850 | struct dsa_mall_mirror_tc_entry *mirror) | |
c2e86691 | 851 | { |
fee34dd1 | 852 | bool in_use = false; |
c2e86691 | 853 | u8 data; |
fee34dd1 | 854 | int p; |
c2e86691 TH |
855 | |
856 | if (mirror->ingress) | |
857 | ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_RX, false); | |
858 | else | |
859 | ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_TX, false); | |
860 | ||
c2e86691 | 861 | |
fee34dd1 | 862 | /* Check if any of the port is still referring to sniffer port */ |
462d5250 | 863 | for (p = 0; p < dev->info->port_cnt; p++) { |
fee34dd1 AR |
864 | ksz_pread8(dev, p, P_MIRROR_CTRL, &data); |
865 | ||
866 | if ((data & (PORT_MIRROR_RX | PORT_MIRROR_TX))) { | |
867 | in_use = true; | |
868 | break; | |
869 | } | |
870 | } | |
871 | ||
872 | /* delete sniffing if there are no other mirroring rules */ | |
873 | if (!in_use) | |
c2e86691 TH |
874 | ksz_port_cfg(dev, mirror->to_local_port, P_MIRROR_CTRL, |
875 | PORT_MIRROR_SNIFFER, false); | |
876 | } | |
877 | ||
8c29bebb TH |
878 | static phy_interface_t ksz9477_get_interface(struct ksz_device *dev, int port) |
879 | { | |
880 | phy_interface_t interface; | |
881 | bool gbit; | |
8c29bebb TH |
882 | |
883 | if (port < dev->phy_port_cnt) | |
884 | return PHY_INTERFACE_MODE_NA; | |
0ab7f6bf | 885 | |
46f80fa8 | 886 | gbit = ksz_get_gbit(dev, port); |
0ab7f6bf AR |
887 | |
888 | interface = ksz_get_xmii(dev, port, gbit); | |
889 | ||
8c29bebb | 890 | return interface; |
42fc6a4c TH |
891 | } |
892 | ||
1fc33199 RH |
893 | static void ksz9477_port_mmd_write(struct ksz_device *dev, int port, |
894 | u8 dev_addr, u16 reg_addr, u16 val) | |
895 | { | |
896 | ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_SETUP, | |
897 | MMD_SETUP(PORT_MMD_OP_INDEX, dev_addr)); | |
898 | ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_INDEX_DATA, reg_addr); | |
899 | ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_SETUP, | |
900 | MMD_SETUP(PORT_MMD_OP_DATA_NO_INCR, dev_addr)); | |
901 | ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_INDEX_DATA, val); | |
902 | } | |
903 | ||
904 | static void ksz9477_phy_errata_setup(struct ksz_device *dev, int port) | |
905 | { | |
906 | /* Apply PHY settings to address errata listed in | |
907 | * KSZ9477, KSZ9897, KSZ9896, KSZ9567, KSZ8565 | |
908 | * Silicon Errata and Data Sheet Clarification documents: | |
909 | * | |
910 | * Register settings are needed to improve PHY receive performance | |
911 | */ | |
912 | ksz9477_port_mmd_write(dev, port, 0x01, 0x6f, 0xdd0b); | |
913 | ksz9477_port_mmd_write(dev, port, 0x01, 0x8f, 0x6032); | |
914 | ksz9477_port_mmd_write(dev, port, 0x01, 0x9d, 0x248c); | |
915 | ksz9477_port_mmd_write(dev, port, 0x01, 0x75, 0x0060); | |
916 | ksz9477_port_mmd_write(dev, port, 0x01, 0xd3, 0x7777); | |
917 | ksz9477_port_mmd_write(dev, port, 0x1c, 0x06, 0x3008); | |
918 | ksz9477_port_mmd_write(dev, port, 0x1c, 0x08, 0x2001); | |
919 | ||
920 | /* Transmit waveform amplitude can be improved | |
921 | * (1000BASE-T, 100BASE-TX, 10BASE-Te) | |
922 | */ | |
923 | ksz9477_port_mmd_write(dev, port, 0x1c, 0x04, 0x00d0); | |
924 | ||
925 | /* Energy Efficient Ethernet (EEE) feature select must | |
926 | * be manually disabled (except on KSZ8565 which is 100Mbit) | |
927 | */ | |
505bf320 | 928 | if (dev->info->gbit_capable[port]) |
1fc33199 RH |
929 | ksz9477_port_mmd_write(dev, port, 0x07, 0x3c, 0x0000); |
930 | ||
931 | /* Register settings are required to meet data sheet | |
932 | * supply current specifications | |
933 | */ | |
934 | ksz9477_port_mmd_write(dev, port, 0x1c, 0x13, 0x6eff); | |
935 | ksz9477_port_mmd_write(dev, port, 0x1c, 0x14, 0xe6ff); | |
936 | ksz9477_port_mmd_write(dev, port, 0x1c, 0x15, 0x6eff); | |
937 | ksz9477_port_mmd_write(dev, port, 0x1c, 0x16, 0xe6ff); | |
938 | ksz9477_port_mmd_write(dev, port, 0x1c, 0x17, 0x00ff); | |
939 | ksz9477_port_mmd_write(dev, port, 0x1c, 0x18, 0x43ff); | |
940 | ksz9477_port_mmd_write(dev, port, 0x1c, 0x19, 0xc3ff); | |
941 | ksz9477_port_mmd_write(dev, port, 0x1c, 0x1a, 0x6fff); | |
942 | ksz9477_port_mmd_write(dev, port, 0x1c, 0x1b, 0x07ff); | |
943 | ksz9477_port_mmd_write(dev, port, 0x1c, 0x1c, 0x0fff); | |
944 | ksz9477_port_mmd_write(dev, port, 0x1c, 0x1d, 0xe7ff); | |
945 | ksz9477_port_mmd_write(dev, port, 0x1c, 0x1e, 0xefff); | |
946 | ksz9477_port_mmd_write(dev, port, 0x1c, 0x20, 0xeeee); | |
947 | } | |
948 | ||
6ec23aaa AR |
949 | void ksz9477_get_caps(struct ksz_device *dev, int port, |
950 | struct phylink_config *config) | |
65ac79e1 | 951 | { |
7a8988a1 AR |
952 | config->mac_capabilities = MAC_10 | MAC_100 | MAC_ASYM_PAUSE | |
953 | MAC_SYM_PAUSE; | |
954 | ||
505bf320 | 955 | if (dev->info->gbit_capable[port]) |
7a8988a1 | 956 | config->mac_capabilities |= MAC_1000FD; |
65ac79e1 AR |
957 | } |
958 | ||
6ec23aaa | 959 | void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port) |
c2e86691 | 960 | { |
b3612ccd | 961 | struct dsa_switch *ds = dev->ds; |
b3612ccd | 962 | u16 data16; |
0ab7f6bf | 963 | u8 member; |
c2e86691 TH |
964 | |
965 | /* enable tag tail for host port */ | |
966 | if (cpu_port) | |
967 | ksz_port_cfg(dev, port, REG_PORT_CTRL_0, PORT_TAIL_TAG_ENABLE, | |
968 | true); | |
969 | ||
970 | ksz_port_cfg(dev, port, REG_PORT_CTRL_0, PORT_MAC_LOOPBACK, false); | |
971 | ||
972 | /* set back pressure */ | |
973 | ksz_port_cfg(dev, port, REG_PORT_MAC_CTRL_1, PORT_BACK_PRESSURE, true); | |
974 | ||
975 | /* enable broadcast storm limit */ | |
976 | ksz_port_cfg(dev, port, P_BCAST_STORM_CTRL, PORT_BROADCAST_STORM, true); | |
977 | ||
978 | /* disable DiffServ priority */ | |
979 | ksz_port_cfg(dev, port, P_PRIO_CTRL, PORT_DIFFSERV_PRIO_ENABLE, false); | |
980 | ||
981 | /* replace priority */ | |
982 | ksz_port_cfg(dev, port, REG_PORT_MRI_MAC_CTRL, PORT_USER_PRIO_CEILING, | |
983 | false); | |
984 | ksz9477_port_cfg32(dev, port, REG_PORT_MTI_QUEUE_CTRL_0__4, | |
985 | MTI_PVID_REPLACE, false); | |
986 | ||
987 | /* enable 802.1p priority */ | |
988 | ksz_port_cfg(dev, port, P_PRIO_CTRL, PORT_802_1P_PRIO_ENABLE, true); | |
989 | ||
990 | if (port < dev->phy_port_cnt) { | |
991 | /* do not force flow control */ | |
992 | ksz_port_cfg(dev, port, REG_PORT_CTRL_0, | |
993 | PORT_FORCE_TX_FLOW_CTRL | PORT_FORCE_RX_FLOW_CTRL, | |
994 | false); | |
995 | ||
462d5250 | 996 | if (dev->info->phy_errata_9477) |
1fc33199 | 997 | ksz9477_phy_errata_setup(dev, port); |
c2e86691 TH |
998 | } else { |
999 | /* force flow control */ | |
1000 | ksz_port_cfg(dev, port, REG_PORT_CTRL_0, | |
1001 | PORT_FORCE_TX_FLOW_CTRL | PORT_FORCE_RX_FLOW_CTRL, | |
1002 | true); | |
c2e86691 | 1003 | } |
b3612ccd | 1004 | |
b20a6b29 | 1005 | if (cpu_port) |
b3612ccd | 1006 | member = dsa_user_ports(ds); |
b20a6b29 | 1007 | else |
b3612ccd OR |
1008 | member = BIT(dsa_upstream_port(ds, port)); |
1009 | ||
c2e86691 TH |
1010 | ksz9477_cfg_port_member(dev, port, member); |
1011 | ||
1012 | /* clear pending interrupts */ | |
1013 | if (port < dev->phy_port_cnt) | |
1014 | ksz_pread16(dev, port, REG_PORT_PHY_INT_ENABLE, &data16); | |
1015 | } | |
1016 | ||
6ec23aaa | 1017 | void ksz9477_config_cpu_port(struct dsa_switch *ds) |
c2e86691 TH |
1018 | { |
1019 | struct ksz_device *dev = ds->priv; | |
1020 | struct ksz_port *p; | |
1021 | int i; | |
1022 | ||
462d5250 AR |
1023 | for (i = 0; i < dev->info->port_cnt; i++) { |
1024 | if (dsa_is_cpu_port(ds, i) && | |
1025 | (dev->info->cpu_ports & (1 << i))) { | |
8c29bebb | 1026 | phy_interface_t interface; |
805a7e6f PB |
1027 | const char *prev_msg; |
1028 | const char *prev_mode; | |
8c29bebb | 1029 | |
c2e86691 | 1030 | dev->cpu_port = i; |
edecfa98 | 1031 | p = &dev->ports[i]; |
c2e86691 | 1032 | |
8c29bebb TH |
1033 | /* Read from XMII register to determine host port |
1034 | * interface. If set specifically in device tree | |
1035 | * note the difference to help debugging. | |
1036 | */ | |
1037 | interface = ksz9477_get_interface(dev, i); | |
edecfa98 HG |
1038 | if (!p->interface) { |
1039 | if (dev->compat_interface) { | |
1040 | dev_warn(dev->dev, | |
1041 | "Using legacy switch \"phy-mode\" property, because it is missing on port %d node. " | |
1042 | "Please update your device tree.\n", | |
1043 | i); | |
1044 | p->interface = dev->compat_interface; | |
1045 | } else { | |
1046 | p->interface = interface; | |
1047 | } | |
1048 | } | |
3ab0a7a0 | 1049 | if (interface && interface != p->interface) { |
805a7e6f PB |
1050 | prev_msg = " instead of "; |
1051 | prev_mode = phy_modes(interface); | |
1052 | } else { | |
1053 | prev_msg = ""; | |
1054 | prev_mode = ""; | |
1055 | } | |
1056 | dev_info(dev->dev, | |
1057 | "Port%d: using phy mode %s%s%s\n", | |
1058 | i, | |
3ab0a7a0 | 1059 | phy_modes(p->interface), |
805a7e6f PB |
1060 | prev_msg, |
1061 | prev_mode); | |
8c29bebb | 1062 | |
c2e86691 TH |
1063 | /* enable cpu port */ |
1064 | ksz9477_port_setup(dev, i, true); | |
c2e86691 TH |
1065 | p->on = 1; |
1066 | } | |
1067 | } | |
1068 | ||
462d5250 | 1069 | for (i = 0; i < dev->info->port_cnt; i++) { |
c2e86691 TH |
1070 | if (i == dev->cpu_port) |
1071 | continue; | |
1072 | p = &dev->ports[i]; | |
1073 | ||
e593df51 | 1074 | ksz_port_stp_state_set(ds, i, BR_STATE_DISABLED); |
c2e86691 TH |
1075 | p->on = 1; |
1076 | if (i < dev->phy_port_cnt) | |
1077 | p->phy = 1; | |
1078 | if (dev->chip_id == 0x00947700 && i == 6) { | |
1079 | p->sgmii = 1; | |
1080 | ||
1081 | /* SGMII PHY detection code is not implemented yet. */ | |
1082 | p->phy = 0; | |
1083 | } | |
1084 | } | |
1085 | } | |
1086 | ||
6ec23aaa | 1087 | int ksz9477_enable_stp_addr(struct ksz_device *dev) |
331d64f7 | 1088 | { |
457c182a | 1089 | const u32 *masks; |
331d64f7 AR |
1090 | u32 data; |
1091 | int ret; | |
1092 | ||
457c182a AR |
1093 | masks = dev->info->masks; |
1094 | ||
331d64f7 AR |
1095 | /* Enable Reserved multicast table */ |
1096 | ksz_cfg(dev, REG_SW_LUE_CTRL_0, SW_RESV_MCAST_ENABLE, true); | |
1097 | ||
1098 | /* Set the Override bit for forwarding BPDU packet to CPU */ | |
1099 | ret = ksz_write32(dev, REG_SW_ALU_VAL_B, | |
1100 | ALU_V_OVERRIDE | BIT(dev->cpu_port)); | |
1101 | if (ret < 0) | |
1102 | return ret; | |
1103 | ||
457c182a | 1104 | data = ALU_STAT_START | ALU_RESV_MCAST_ADDR | masks[ALU_STAT_WRITE]; |
331d64f7 AR |
1105 | |
1106 | ret = ksz_write32(dev, REG_SW_ALU_STAT_CTRL__4, data); | |
1107 | if (ret < 0) | |
1108 | return ret; | |
1109 | ||
1110 | /* wait to be finished */ | |
1111 | ret = ksz9477_wait_alu_sta_ready(dev); | |
1112 | if (ret < 0) { | |
1113 | dev_err(dev->dev, "Failed to update Reserved Multicast table\n"); | |
1114 | return ret; | |
1115 | } | |
1116 | ||
1117 | return 0; | |
1118 | } | |
1119 | ||
6ec23aaa | 1120 | int ksz9477_setup(struct dsa_switch *ds) |
c2e86691 TH |
1121 | { |
1122 | struct ksz_device *dev = ds->priv; | |
1123 | int ret = 0; | |
1124 | ||
962ad710 TH |
1125 | /* Required for port partitioning. */ |
1126 | ksz9477_cfg32(dev, REG_SW_QM_CTRL__4, UNICAST_VLAN_BOUNDARY, | |
1127 | true); | |
1128 | ||
8c29bebb TH |
1129 | /* Do not work correctly with tail tagging. */ |
1130 | ksz_cfg(dev, REG_SW_MAC_CTRL_0, SW_CHECK_LENGTH, false); | |
1131 | ||
e18058ea OR |
1132 | /* Enable REG_SW_MTU__2 reg by setting SW_JUMBO_PACKET */ |
1133 | ksz_cfg(dev, REG_SW_MAC_CTRL_1, SW_JUMBO_PACKET, true); | |
1134 | ||
1135 | /* Now we can configure default MTU value */ | |
1136 | ret = regmap_update_bits(dev->regmap[1], REG_SW_MTU__2, REG_SW_MTU_MASK, | |
1137 | VLAN_ETH_FRAME_LEN + ETH_FCS_LEN); | |
1138 | if (ret) | |
1139 | return ret; | |
c2e86691 | 1140 | |
c2e86691 TH |
1141 | /* queue based egress rate limit */ |
1142 | ksz_cfg(dev, REG_SW_MAC_CTRL_5, SW_OUT_RATE_LIMIT_QUEUE_BASED, true); | |
1143 | ||
7c6ff470 TH |
1144 | /* enable global MIB counter freeze function */ |
1145 | ksz_cfg(dev, REG_SW_MAC_CTRL_6, SW_MIB_COUNTER_FREEZE, true); | |
1146 | ||
c2e86691 TH |
1147 | return 0; |
1148 | } | |
1149 | ||
6ec23aaa | 1150 | u32 ksz9477_get_port_addr(int port, int offset) |
c2e86691 TH |
1151 | { |
1152 | return PORT_CTRL_ADDR(port, offset); | |
1153 | } | |
1154 | ||
6ec23aaa | 1155 | int ksz9477_switch_init(struct ksz_device *dev) |
27faa0aa AR |
1156 | { |
1157 | u8 data8; | |
1158 | int ret; | |
1159 | ||
27faa0aa AR |
1160 | dev->port_mask = (1 << dev->info->port_cnt) - 1; |
1161 | ||
c2e86691 TH |
1162 | /* turn off SPI DO Edge select */ |
1163 | ret = ksz_read8(dev, REG_SW_GLOBAL_SERIAL_CTRL_0, &data8); | |
1164 | if (ret) | |
1165 | return ret; | |
1166 | ||
1167 | data8 &= ~SPI_AUTO_EDGE_DETECTION; | |
1168 | ret = ksz_write8(dev, REG_SW_GLOBAL_SERIAL_CTRL_0, data8); | |
1169 | if (ret) | |
1170 | return ret; | |
1171 | ||
c2e86691 | 1172 | /* Number of ports can be reduced depending on chip. */ |
c2e86691 TH |
1173 | dev->phy_port_cnt = 5; |
1174 | ||
27faa0aa | 1175 | if (dev->chip_id == KSZ9893_CHIP_ID) { |
8c29bebb TH |
1176 | dev->features |= IS_9893; |
1177 | ||
8c29bebb | 1178 | dev->phy_port_cnt = 2; |
8c29bebb | 1179 | } |
1958eee8 | 1180 | |
c2e86691 TH |
1181 | return 0; |
1182 | } | |
1183 | ||
6ec23aaa | 1184 | void ksz9477_switch_exit(struct ksz_device *dev) |
c2e86691 TH |
1185 | { |
1186 | ksz9477_reset_switch(dev); | |
1187 | } | |
1188 | ||
c2e86691 TH |
1189 | MODULE_AUTHOR("Woojung Huh <Woojung.Huh@microchip.com>"); |
1190 | MODULE_DESCRIPTION("Microchip KSZ9477 Series Switch DSA Driver"); | |
1191 | MODULE_LICENSE("GPL"); |