1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Microchip KSZ8795 switch driver |
4 | * |
5 | * Copyright (C) 2017 Microchip Technology Inc. |
6 | * Tristram Ha <Tristram.Ha@microchip.com> |
7 | */ |
8 | |
9 | #include <linux/bitfield.h> |
10 | #include <linux/delay.h> |
11 | #include <linux/export.h> |
12 | #include <linux/gpio.h> |
13 | #include <linux/if_vlan.h> |
14 | #include <linux/kernel.h> |
15 | #include <linux/module.h> |
16 | #include <linux/platform_data/microchip-ksz.h> |
17 | #include <linux/phy.h> |
18 | #include <linux/etherdevice.h> |
19 | #include <linux/if_bridge.h> |
20 | #include <linux/micrel_phy.h> |
21 | #include <net/dsa.h> |
22 | #include <net/switchdev.h> |
23 | #include <linux/phylink.h> |
24 | |
25 | #include "ksz_common.h" |
26 | #include "ksz8795_reg.h" |
27 | #include "ksz8.h" |
28 | |
29 | static void ksz_cfg(struct ksz_device *dev, u32 addr, u8 bits, bool set) |
30 | { |
31 | regmap_update_bits(map: ksz_regmap_8(dev), reg: addr, mask: bits, val: set ? bits : 0); |
32 | } |
33 | |
34 | static void ksz_port_cfg(struct ksz_device *dev, int port, int offset, u8 bits, |
35 | bool set) |
36 | { |
37 | regmap_update_bits(map: ksz_regmap_8(dev), PORT_CTRL_ADDR(port, offset), |
38 | mask: bits, val: set ? bits : 0); |
39 | } |
40 | |
41 | static int ksz8_ind_write8(struct ksz_device *dev, u8 table, u16 addr, u8 data) |
42 | { |
43 | const u16 *regs; |
44 | u16 ctrl_addr; |
45 | int ret = 0; |
46 | |
47 | regs = dev->info->regs; |
48 | |
49 | mutex_lock(&dev->alu_mutex); |
50 | |
51 | ctrl_addr = IND_ACC_TABLE(table) | addr; |
52 | ret = ksz_write16(dev, reg: regs[REG_IND_CTRL_0], value: ctrl_addr); |
53 | if (!ret) |
54 | ret = ksz_write8(dev, reg: regs[REG_IND_BYTE], value: data); |
55 | |
56 | mutex_unlock(lock: &dev->alu_mutex); |
57 | |
58 | return ret; |
59 | } |
60 | |
61 | int ksz8_reset_switch(struct ksz_device *dev) |
62 | { |
63 | if (ksz_is_ksz88x3(dev)) { |
64 | /* reset switch */ |
65 | ksz_cfg(dev, KSZ8863_REG_SW_RESET, |
66 | KSZ8863_GLOBAL_SOFTWARE_RESET | KSZ8863_PCS_RESET, set: true); |
67 | ksz_cfg(dev, KSZ8863_REG_SW_RESET, |
68 | KSZ8863_GLOBAL_SOFTWARE_RESET | KSZ8863_PCS_RESET, set: false); |
69 | } else { |
70 | /* reset switch */ |
71 | ksz_write8(dev, REG_POWER_MANAGEMENT_1, |
72 | SW_SOFTWARE_POWER_DOWN << SW_POWER_MANAGEMENT_MODE_S); |
73 | ksz_write8(dev, REG_POWER_MANAGEMENT_1, value: 0); |
74 | } |
75 | |
76 | return 0; |
77 | } |
78 | |
79 | static int ksz8863_change_mtu(struct ksz_device *dev, int frame_size) |
80 | { |
81 | u8 ctrl2 = 0; |
82 | |
83 | if (frame_size <= KSZ8_LEGAL_PACKET_SIZE) |
84 | ctrl2 |= KSZ8863_LEGAL_PACKET_ENABLE; |
85 | else if (frame_size > KSZ8863_NORMAL_PACKET_SIZE) |
86 | ctrl2 |= KSZ8863_HUGE_PACKET_ENABLE; |
87 | |
88 | return ksz_rmw8(dev, REG_SW_CTRL_2, KSZ8863_LEGAL_PACKET_ENABLE | |
89 | KSZ8863_HUGE_PACKET_ENABLE, val: ctrl2); |
90 | } |
91 | |
92 | static int ksz8795_change_mtu(struct ksz_device *dev, int frame_size) |
93 | { |
94 | u8 ctrl1 = 0, ctrl2 = 0; |
95 | int ret; |
96 | |
97 | if (frame_size > KSZ8_LEGAL_PACKET_SIZE) |
98 | ctrl2 |= SW_LEGAL_PACKET_DISABLE; |
99 | if (frame_size > KSZ8863_NORMAL_PACKET_SIZE) |
100 | ctrl1 |= SW_HUGE_PACKET; |
101 | |
102 | ret = ksz_rmw8(dev, REG_SW_CTRL_1, SW_HUGE_PACKET, val: ctrl1); |
103 | if (ret) |
104 | return ret; |
105 | |
106 | return ksz_rmw8(dev, REG_SW_CTRL_2, SW_LEGAL_PACKET_DISABLE, val: ctrl2); |
107 | } |
108 | |
109 | int ksz8_change_mtu(struct ksz_device *dev, int port, int mtu) |
110 | { |
111 | u16 frame_size; |
112 | |
113 | if (!dsa_is_cpu_port(ds: dev->ds, p: port)) |
114 | return 0; |
115 | |
116 | frame_size = mtu + VLAN_ETH_HLEN + ETH_FCS_LEN; |
117 | |
118 | switch (dev->chip_id) { |
119 | case KSZ8795_CHIP_ID: |
120 | case KSZ8794_CHIP_ID: |
121 | case KSZ8765_CHIP_ID: |
122 | return ksz8795_change_mtu(dev, frame_size); |
123 | case KSZ8830_CHIP_ID: |
124 | return ksz8863_change_mtu(dev, frame_size); |
125 | } |
126 | |
127 | return -EOPNOTSUPP; |
128 | } |
129 | |
130 | static void ksz8795_set_prio_queue(struct ksz_device *dev, int port, int queue) |
131 | { |
132 | u8 hi, lo; |
133 | |
134 | /* Number of queues can only be 1, 2, or 4. */ |
135 | switch (queue) { |
136 | case 4: |
137 | case 3: |
138 | queue = PORT_QUEUE_SPLIT_4; |
139 | break; |
140 | case 2: |
141 | queue = PORT_QUEUE_SPLIT_2; |
142 | break; |
143 | default: |
144 | queue = PORT_QUEUE_SPLIT_1; |
145 | } |
146 | ksz_pread8(dev, port, REG_PORT_CTRL_0, data: &lo); |
147 | ksz_pread8(dev, port, P_DROP_TAG_CTRL, data: &hi); |
148 | lo &= ~PORT_QUEUE_SPLIT_L; |
149 | if (queue & PORT_QUEUE_SPLIT_2) |
150 | lo |= PORT_QUEUE_SPLIT_L; |
151 | hi &= ~PORT_QUEUE_SPLIT_H; |
152 | if (queue & PORT_QUEUE_SPLIT_4) |
153 | hi |= PORT_QUEUE_SPLIT_H; |
154 | ksz_pwrite8(dev, port, REG_PORT_CTRL_0, data: lo); |
155 | ksz_pwrite8(dev, port, P_DROP_TAG_CTRL, data: hi); |
156 | |
157 | /* Default is port based for egress rate limit. */ |
158 | if (queue != PORT_QUEUE_SPLIT_1) |
159 | ksz_cfg(dev, REG_SW_CTRL_19, SW_OUT_RATE_LIMIT_QUEUE_BASED, |
160 | set: true); |
161 | } |
162 | |
163 | void ksz8_r_mib_cnt(struct ksz_device *dev, int port, u16 addr, u64 *cnt) |
164 | { |
165 | const u32 *masks; |
166 | const u16 *regs; |
167 | u16 ctrl_addr; |
168 | u32 data; |
169 | u8 check; |
170 | int loop; |
171 | |
172 | masks = dev->info->masks; |
173 | regs = dev->info->regs; |
174 | |
175 | ctrl_addr = addr + dev->info->reg_mib_cnt * port; |
176 | ctrl_addr |= IND_ACC_TABLE(TABLE_MIB | TABLE_READ); |
177 | |
178 | mutex_lock(&dev->alu_mutex); |
179 | ksz_write16(dev, reg: regs[REG_IND_CTRL_0], value: ctrl_addr); |
180 | |
181 | /* It is almost guaranteed to always read the valid bit because of |
182 | * slow SPI speed. |
183 | */ |
184 | for (loop = 2; loop > 0; loop--) { |
185 | ksz_read8(dev, reg: regs[REG_IND_MIB_CHECK], val: &check); |
186 | |
187 | if (check & masks[MIB_COUNTER_VALID]) { |
188 | ksz_read32(dev, reg: regs[REG_IND_DATA_LO], val: &data); |
189 | if (check & masks[MIB_COUNTER_OVERFLOW]) |
190 | *cnt += MIB_COUNTER_VALUE + 1; |
191 | *cnt += data & MIB_COUNTER_VALUE; |
192 | break; |
193 | } |
194 | } |
195 | mutex_unlock(lock: &dev->alu_mutex); |
196 | } |
197 | |
198 | static void ksz8795_r_mib_pkt(struct ksz_device *dev, int port, u16 addr, |
199 | u64 *dropped, u64 *cnt) |
200 | { |
201 | const u32 *masks; |
202 | const u16 *regs; |
203 | u16 ctrl_addr; |
204 | u32 data; |
205 | u8 check; |
206 | int loop; |
207 | |
208 | masks = dev->info->masks; |
209 | regs = dev->info->regs; |
210 | |
211 | addr -= dev->info->reg_mib_cnt; |
212 | ctrl_addr = (KSZ8795_MIB_TOTAL_RX_1 - KSZ8795_MIB_TOTAL_RX_0) * port; |
213 | ctrl_addr += addr + KSZ8795_MIB_TOTAL_RX_0; |
214 | ctrl_addr |= IND_ACC_TABLE(TABLE_MIB | TABLE_READ); |
215 | |
216 | mutex_lock(&dev->alu_mutex); |
217 | ksz_write16(dev, reg: regs[REG_IND_CTRL_0], value: ctrl_addr); |
218 | |
219 | /* It is almost guaranteed to always read the valid bit because of |
220 | * slow SPI speed. |
221 | */ |
222 | for (loop = 2; loop > 0; loop--) { |
223 | ksz_read8(dev, reg: regs[REG_IND_MIB_CHECK], val: &check); |
224 | |
225 | if (check & masks[MIB_COUNTER_VALID]) { |
226 | ksz_read32(dev, reg: regs[REG_IND_DATA_LO], val: &data); |
227 | if (addr < 2) { |
228 | u64 total; |
229 | |
230 | total = check & MIB_TOTAL_BYTES_H; |
231 | total <<= 32; |
232 | *cnt += total; |
233 | *cnt += data; |
234 | if (check & masks[MIB_COUNTER_OVERFLOW]) { |
235 | total = MIB_TOTAL_BYTES_H + 1; |
236 | total <<= 32; |
237 | *cnt += total; |
238 | } |
239 | } else { |
240 | if (check & masks[MIB_COUNTER_OVERFLOW]) |
241 | *cnt += MIB_PACKET_DROPPED + 1; |
242 | *cnt += data & MIB_PACKET_DROPPED; |
243 | } |
244 | break; |
245 | } |
246 | } |
247 | mutex_unlock(lock: &dev->alu_mutex); |
248 | } |
249 | |
250 | static void ksz8863_r_mib_pkt(struct ksz_device *dev, int port, u16 addr, |
251 | u64 *dropped, u64 *cnt) |
252 | { |
253 | u32 *last = (u32 *)dropped; |
254 | const u16 *regs; |
255 | u16 ctrl_addr; |
256 | u32 data; |
257 | u32 cur; |
258 | |
259 | regs = dev->info->regs; |
260 | |
261 | addr -= dev->info->reg_mib_cnt; |
262 | ctrl_addr = addr ? KSZ8863_MIB_PACKET_DROPPED_TX_0 : |
263 | KSZ8863_MIB_PACKET_DROPPED_RX_0; |
264 | ctrl_addr += port; |
265 | ctrl_addr |= IND_ACC_TABLE(TABLE_MIB | TABLE_READ); |
266 | |
267 | mutex_lock(&dev->alu_mutex); |
268 | ksz_write16(dev, reg: regs[REG_IND_CTRL_0], value: ctrl_addr); |
269 | ksz_read32(dev, reg: regs[REG_IND_DATA_LO], val: &data); |
270 | mutex_unlock(lock: &dev->alu_mutex); |
271 | |
272 | data &= MIB_PACKET_DROPPED; |
273 | cur = last[addr]; |
274 | if (data != cur) { |
275 | last[addr] = data; |
276 | if (data < cur) |
277 | data += MIB_PACKET_DROPPED + 1; |
278 | data -= cur; |
279 | *cnt += data; |
280 | } |
281 | } |
282 | |
283 | void ksz8_r_mib_pkt(struct ksz_device *dev, int port, u16 addr, |
284 | u64 *dropped, u64 *cnt) |
285 | { |
286 | if (ksz_is_ksz88x3(dev)) |
287 | ksz8863_r_mib_pkt(dev, port, addr, dropped, cnt); |
288 | else |
289 | ksz8795_r_mib_pkt(dev, port, addr, dropped, cnt); |
290 | } |
291 | |
292 | void ksz8_freeze_mib(struct ksz_device *dev, int port, bool freeze) |
293 | { |
294 | if (ksz_is_ksz88x3(dev)) |
295 | return; |
296 | |
297 | /* enable the port for flush/freeze function */ |
298 | if (freeze) |
299 | ksz_cfg(dev, REG_SW_CTRL_6, BIT(port), set: true); |
300 | ksz_cfg(dev, REG_SW_CTRL_6, SW_MIB_COUNTER_FREEZE, set: freeze); |
301 | |
302 | /* disable the port after freeze is done */ |
303 | if (!freeze) |
304 | ksz_cfg(dev, REG_SW_CTRL_6, BIT(port), set: false); |
305 | } |
306 | |
307 | void ksz8_port_init_cnt(struct ksz_device *dev, int port) |
308 | { |
309 | struct ksz_port_mib *mib = &dev->ports[port].mib; |
310 | u64 *dropped; |
311 | |
312 | if (!ksz_is_ksz88x3(dev)) { |
313 | /* flush all enabled port MIB counters */ |
314 | ksz_cfg(dev, REG_SW_CTRL_6, BIT(port), set: true); |
315 | ksz_cfg(dev, REG_SW_CTRL_6, SW_MIB_COUNTER_FLUSH, set: true); |
316 | ksz_cfg(dev, REG_SW_CTRL_6, BIT(port), set: false); |
317 | } |
318 | |
319 | mib->cnt_ptr = 0; |
320 | |
321 | /* Some ports may not have MIB counters before SWITCH_COUNTER_NUM. */ |
322 | while (mib->cnt_ptr < dev->info->reg_mib_cnt) { |
323 | dev->dev_ops->r_mib_cnt(dev, port, mib->cnt_ptr, |
324 | &mib->counters[mib->cnt_ptr]); |
325 | ++mib->cnt_ptr; |
326 | } |
327 | |
328 | /* last one in storage */ |
329 | dropped = &mib->counters[dev->info->mib_cnt]; |
330 | |
331 | /* Some ports may not have MIB counters after SWITCH_COUNTER_NUM. */ |
332 | while (mib->cnt_ptr < dev->info->mib_cnt) { |
333 | dev->dev_ops->r_mib_pkt(dev, port, mib->cnt_ptr, |
334 | dropped, &mib->counters[mib->cnt_ptr]); |
335 | ++mib->cnt_ptr; |
336 | } |
337 | } |
338 | |
339 | static int ksz8_r_table(struct ksz_device *dev, int table, u16 addr, u64 *data) |
340 | { |
341 | const u16 *regs; |
342 | u16 ctrl_addr; |
343 | int ret; |
344 | |
345 | regs = dev->info->regs; |
346 | |
347 | ctrl_addr = IND_ACC_TABLE(table | TABLE_READ) | addr; |
348 | |
349 | mutex_lock(&dev->alu_mutex); |
350 | ret = ksz_write16(dev, reg: regs[REG_IND_CTRL_0], value: ctrl_addr); |
351 | if (ret) |
352 | goto unlock_alu; |
353 | |
354 | ret = ksz_read64(dev, reg: regs[REG_IND_DATA_HI], val: data); |
355 | unlock_alu: |
356 | mutex_unlock(lock: &dev->alu_mutex); |
357 | |
358 | return ret; |
359 | } |
360 | |
361 | static int ksz8_w_table(struct ksz_device *dev, int table, u16 addr, u64 data) |
362 | { |
363 | const u16 *regs; |
364 | u16 ctrl_addr; |
365 | int ret; |
366 | |
367 | regs = dev->info->regs; |
368 | |
369 | ctrl_addr = IND_ACC_TABLE(table) | addr; |
370 | |
371 | mutex_lock(&dev->alu_mutex); |
372 | ret = ksz_write64(dev, reg: regs[REG_IND_DATA_HI], value: data); |
373 | if (ret) |
374 | goto unlock_alu; |
375 | |
376 | ret = ksz_write16(dev, reg: regs[REG_IND_CTRL_0], value: ctrl_addr); |
377 | unlock_alu: |
378 | mutex_unlock(lock: &dev->alu_mutex); |
379 | |
380 | return ret; |
381 | } |
382 | |
383 | static int ksz8_valid_dyn_entry(struct ksz_device *dev, u8 *data) |
384 | { |
385 | int timeout = 100; |
386 | const u32 *masks; |
387 | const u16 *regs; |
388 | |
389 | masks = dev->info->masks; |
390 | regs = dev->info->regs; |
391 | |
392 | do { |
393 | ksz_read8(dev, reg: regs[REG_IND_DATA_CHECK], val: data); |
394 | timeout--; |
395 | } while ((*data & masks[DYNAMIC_MAC_TABLE_NOT_READY]) && timeout); |
396 | |
397 | /* Entry is not ready for accessing. */ |
398 | if (*data & masks[DYNAMIC_MAC_TABLE_NOT_READY]) { |
399 | return -EAGAIN; |
400 | /* Entry is ready for accessing. */ |
401 | } else { |
402 | ksz_read8(dev, reg: regs[REG_IND_DATA_8], val: data); |
403 | |
404 | /* There is no valid entry in the table. */ |
405 | if (*data & masks[DYNAMIC_MAC_TABLE_MAC_EMPTY]) |
406 | return -ENXIO; |
407 | } |
408 | return 0; |
409 | } |
410 | |
411 | int ksz8_r_dyn_mac_table(struct ksz_device *dev, u16 addr, u8 *mac_addr, |
412 | u8 *fid, u8 *src_port, u8 *timestamp, u16 *entries) |
413 | { |
414 | u32 data_hi, data_lo; |
415 | const u8 *shifts; |
416 | const u32 *masks; |
417 | const u16 *regs; |
418 | u16 ctrl_addr; |
419 | u8 data; |
420 | int rc; |
421 | |
422 | shifts = dev->info->shifts; |
423 | masks = dev->info->masks; |
424 | regs = dev->info->regs; |
425 | |
426 | ctrl_addr = IND_ACC_TABLE(TABLE_DYNAMIC_MAC | TABLE_READ) | addr; |
427 | |
428 | mutex_lock(&dev->alu_mutex); |
429 | ksz_write16(dev, reg: regs[REG_IND_CTRL_0], value: ctrl_addr); |
430 | |
431 | rc = ksz8_valid_dyn_entry(dev, data: &data); |
432 | if (rc == -EAGAIN) { |
433 | if (addr == 0) |
434 | *entries = 0; |
435 | } else if (rc == -ENXIO) { |
436 | *entries = 0; |
437 | /* At least one valid entry in the table. */ |
438 | } else { |
439 | u64 buf = 0; |
440 | int cnt; |
441 | |
442 | ksz_read64(dev, reg: regs[REG_IND_DATA_HI], val: &buf); |
443 | data_hi = (u32)(buf >> 32); |
444 | data_lo = (u32)buf; |
445 | |
446 | /* Check out how many valid entry in the table. */ |
447 | cnt = data & masks[DYNAMIC_MAC_TABLE_ENTRIES_H]; |
448 | cnt <<= shifts[DYNAMIC_MAC_ENTRIES_H]; |
449 | cnt |= (data_hi & masks[DYNAMIC_MAC_TABLE_ENTRIES]) >> |
450 | shifts[DYNAMIC_MAC_ENTRIES]; |
451 | *entries = cnt + 1; |
452 | |
453 | *fid = (data_hi & masks[DYNAMIC_MAC_TABLE_FID]) >> |
454 | shifts[DYNAMIC_MAC_FID]; |
455 | *src_port = (data_hi & masks[DYNAMIC_MAC_TABLE_SRC_PORT]) >> |
456 | shifts[DYNAMIC_MAC_SRC_PORT]; |
457 | *timestamp = (data_hi & masks[DYNAMIC_MAC_TABLE_TIMESTAMP]) >> |
458 | shifts[DYNAMIC_MAC_TIMESTAMP]; |
459 | |
460 | mac_addr[5] = (u8)data_lo; |
461 | mac_addr[4] = (u8)(data_lo >> 8); |
462 | mac_addr[3] = (u8)(data_lo >> 16); |
463 | mac_addr[2] = (u8)(data_lo >> 24); |
464 | |
465 | mac_addr[1] = (u8)data_hi; |
466 | mac_addr[0] = (u8)(data_hi >> 8); |
467 | rc = 0; |
468 | } |
469 | mutex_unlock(lock: &dev->alu_mutex); |
470 | |
471 | return rc; |
472 | } |
473 | |
474 | static int ksz8_r_sta_mac_table(struct ksz_device *dev, u16 addr, |
475 | struct alu_struct *alu, bool *valid) |
476 | { |
477 | u32 data_hi, data_lo; |
478 | const u8 *shifts; |
479 | const u32 *masks; |
480 | u64 data; |
481 | int ret; |
482 | |
483 | shifts = dev->info->shifts; |
484 | masks = dev->info->masks; |
485 | |
486 | ret = ksz8_r_table(dev, TABLE_STATIC_MAC, addr, data: &data); |
487 | if (ret) |
488 | return ret; |
489 | |
490 | data_hi = data >> 32; |
491 | data_lo = (u32)data; |
492 | |
493 | if (!(data_hi & (masks[STATIC_MAC_TABLE_VALID] | |
494 | masks[STATIC_MAC_TABLE_OVERRIDE]))) { |
495 | *valid = false; |
496 | return 0; |
497 | } |
498 | |
499 | alu->mac[5] = (u8)data_lo; |
500 | alu->mac[4] = (u8)(data_lo >> 8); |
501 | alu->mac[3] = (u8)(data_lo >> 16); |
502 | alu->mac[2] = (u8)(data_lo >> 24); |
503 | alu->mac[1] = (u8)data_hi; |
504 | alu->mac[0] = (u8)(data_hi >> 8); |
505 | alu->port_forward = |
506 | (data_hi & masks[STATIC_MAC_TABLE_FWD_PORTS]) >> |
507 | shifts[STATIC_MAC_FWD_PORTS]; |
508 | alu->is_override = (data_hi & masks[STATIC_MAC_TABLE_OVERRIDE]) ? 1 : 0; |
509 | |
510 | /* KSZ8795 family switches have STATIC_MAC_TABLE_USE_FID and |
511 | * STATIC_MAC_TABLE_FID definitions off by 1 when doing read on the |
512 | * static MAC table compared to doing write. |
513 | */ |
514 | if (ksz_is_ksz87xx(dev)) |
515 | data_hi >>= 1; |
516 | alu->is_static = true; |
517 | alu->is_use_fid = (data_hi & masks[STATIC_MAC_TABLE_USE_FID]) ? 1 : 0; |
518 | alu->fid = (data_hi & masks[STATIC_MAC_TABLE_FID]) >> |
519 | shifts[STATIC_MAC_FID]; |
520 | |
521 | *valid = true; |
522 | |
523 | return 0; |
524 | } |
525 | |
526 | static int ksz8_w_sta_mac_table(struct ksz_device *dev, u16 addr, |
527 | struct alu_struct *alu) |
528 | { |
529 | u32 data_hi, data_lo; |
530 | const u8 *shifts; |
531 | const u32 *masks; |
532 | u64 data; |
533 | |
534 | shifts = dev->info->shifts; |
535 | masks = dev->info->masks; |
536 | |
537 | data_lo = ((u32)alu->mac[2] << 24) | |
538 | ((u32)alu->mac[3] << 16) | |
539 | ((u32)alu->mac[4] << 8) | alu->mac[5]; |
540 | data_hi = ((u32)alu->mac[0] << 8) | alu->mac[1]; |
541 | data_hi |= (u32)alu->port_forward << shifts[STATIC_MAC_FWD_PORTS]; |
542 | |
543 | if (alu->is_override) |
544 | data_hi |= masks[STATIC_MAC_TABLE_OVERRIDE]; |
545 | if (alu->is_use_fid) { |
546 | data_hi |= masks[STATIC_MAC_TABLE_USE_FID]; |
547 | data_hi |= (u32)alu->fid << shifts[STATIC_MAC_FID]; |
548 | } |
549 | if (alu->is_static) |
550 | data_hi |= masks[STATIC_MAC_TABLE_VALID]; |
551 | else |
552 | data_hi &= ~masks[STATIC_MAC_TABLE_OVERRIDE]; |
553 | |
554 | data = (u64)data_hi << 32 | data_lo; |
555 | |
556 | return ksz8_w_table(dev, TABLE_STATIC_MAC, addr, data); |
557 | } |
558 | |
559 | static void ksz8_from_vlan(struct ksz_device *dev, u32 vlan, u8 *fid, |
560 | u8 *member, u8 *valid) |
561 | { |
562 | const u8 *shifts; |
563 | const u32 *masks; |
564 | |
565 | shifts = dev->info->shifts; |
566 | masks = dev->info->masks; |
567 | |
568 | *fid = vlan & masks[VLAN_TABLE_FID]; |
569 | *member = (vlan & masks[VLAN_TABLE_MEMBERSHIP]) >> |
570 | shifts[VLAN_TABLE_MEMBERSHIP_S]; |
571 | *valid = !!(vlan & masks[VLAN_TABLE_VALID]); |
572 | } |
573 | |
574 | static void ksz8_to_vlan(struct ksz_device *dev, u8 fid, u8 member, u8 valid, |
575 | u16 *vlan) |
576 | { |
577 | const u8 *shifts; |
578 | const u32 *masks; |
579 | |
580 | shifts = dev->info->shifts; |
581 | masks = dev->info->masks; |
582 | |
583 | *vlan = fid; |
584 | *vlan |= (u16)member << shifts[VLAN_TABLE_MEMBERSHIP_S]; |
585 | if (valid) |
586 | *vlan |= masks[VLAN_TABLE_VALID]; |
587 | } |
588 | |
589 | static void ksz8_r_vlan_entries(struct ksz_device *dev, u16 addr) |
590 | { |
591 | const u8 *shifts; |
592 | u64 data; |
593 | int i; |
594 | |
595 | shifts = dev->info->shifts; |
596 | |
597 | ksz8_r_table(dev, TABLE_VLAN, addr, data: &data); |
598 | addr *= 4; |
599 | for (i = 0; i < 4; i++) { |
600 | dev->vlan_cache[addr + i].table[0] = (u16)data; |
601 | data >>= shifts[VLAN_TABLE]; |
602 | } |
603 | } |
604 | |
605 | static void ksz8_r_vlan_table(struct ksz_device *dev, u16 vid, u16 *vlan) |
606 | { |
607 | int index; |
608 | u16 *data; |
609 | u16 addr; |
610 | u64 buf; |
611 | |
612 | data = (u16 *)&buf; |
613 | addr = vid / 4; |
614 | index = vid & 3; |
615 | ksz8_r_table(dev, TABLE_VLAN, addr, data: &buf); |
616 | *vlan = data[index]; |
617 | } |
618 | |
619 | static void ksz8_w_vlan_table(struct ksz_device *dev, u16 vid, u16 vlan) |
620 | { |
621 | int index; |
622 | u16 *data; |
623 | u16 addr; |
624 | u64 buf; |
625 | |
626 | data = (u16 *)&buf; |
627 | addr = vid / 4; |
628 | index = vid & 3; |
629 | ksz8_r_table(dev, TABLE_VLAN, addr, data: &buf); |
630 | data[index] = vlan; |
631 | dev->vlan_cache[vid].table[0] = vlan; |
632 | ksz8_w_table(dev, TABLE_VLAN, addr, data: buf); |
633 | } |
634 | |
635 | /** |
636 | * ksz879x_get_loopback - KSZ879x specific function to get loopback |
637 | * configuration status for a specific port |
638 | * @dev: Pointer to the device structure |
639 | * @port: Port number to query |
640 | * @val: Pointer to store the result |
641 | * |
642 | * This function reads the SMI registers to determine whether loopback mode |
643 | * is enabled for a specific port. |
644 | * |
645 | * Return: 0 on success, error code on failure. |
646 | */ |
647 | static int ksz879x_get_loopback(struct ksz_device *dev, u16 port, |
648 | u16 *val) |
649 | { |
650 | u8 stat3; |
651 | int ret; |
652 | |
653 | ret = ksz_pread8(dev, port, REG_PORT_STATUS_3, data: &stat3); |
654 | if (ret) |
655 | return ret; |
656 | |
657 | if (stat3 & PORT_PHY_LOOPBACK) |
658 | *val |= BMCR_LOOPBACK; |
659 | |
660 | return 0; |
661 | } |
662 | |
663 | /** |
664 | * ksz879x_set_loopback - KSZ879x specific function to set loopback mode for |
665 | * a specific port |
666 | * @dev: Pointer to the device structure. |
667 | * @port: Port number to modify. |
668 | * @val: Value indicating whether to enable or disable loopback mode. |
669 | * |
670 | * This function translates loopback bit of the BMCR register into the |
671 | * corresponding hardware register bit value and writes it to the SMI interface. |
672 | * |
673 | * Return: 0 on success, error code on failure. |
674 | */ |
675 | static int ksz879x_set_loopback(struct ksz_device *dev, u16 port, u16 val) |
676 | { |
677 | u8 stat3 = 0; |
678 | |
679 | if (val & BMCR_LOOPBACK) |
680 | stat3 |= PORT_PHY_LOOPBACK; |
681 | |
682 | return ksz_prmw8(dev, port, REG_PORT_STATUS_3, PORT_PHY_LOOPBACK, |
683 | val: stat3); |
684 | } |
685 | |
686 | /** |
687 | * ksz8_r_phy_ctrl - Translates and reads from the SMI interface to a MIIM PHY |
688 | * Control register (Reg. 31). |
689 | * @dev: The KSZ device instance. |
690 | * @port: The port number to be read. |
691 | * @val: The value read from the SMI interface. |
692 | * |
693 | * This function reads the SMI interface and translates the hardware register |
694 | * bit values into their corresponding control settings for a MIIM PHY Control |
695 | * register. |
696 | * |
697 | * Return: 0 on success, error code on failure. |
698 | */ |
699 | static int ksz8_r_phy_ctrl(struct ksz_device *dev, int port, u16 *val) |
700 | { |
701 | const u16 *regs = dev->info->regs; |
702 | u8 reg_val; |
703 | int ret; |
704 | |
705 | *val = 0; |
706 | |
707 | ret = ksz_pread8(dev, port, offset: regs[P_LINK_STATUS], data: ®_val); |
708 | if (ret < 0) |
709 | return ret; |
710 | |
711 | if (reg_val & PORT_MDIX_STATUS) |
712 | *val |= KSZ886X_CTRL_MDIX_STAT; |
713 | |
714 | ret = ksz_pread8(dev, port, REG_PORT_LINK_MD_CTRL, data: ®_val); |
715 | if (ret < 0) |
716 | return ret; |
717 | |
718 | if (reg_val & PORT_FORCE_LINK) |
719 | *val |= KSZ886X_CTRL_FORCE_LINK; |
720 | |
721 | if (reg_val & PORT_POWER_SAVING) |
722 | *val |= KSZ886X_CTRL_PWRSAVE; |
723 | |
724 | if (reg_val & PORT_PHY_REMOTE_LOOPBACK) |
725 | *val |= KSZ886X_CTRL_REMOTE_LOOPBACK; |
726 | |
727 | return 0; |
728 | } |
729 | |
730 | /** |
731 | * ksz8_r_phy_bmcr - Translates and reads from the SMI interface to a MIIM PHY |
732 | * Basic mode control register (Reg. 0). |
733 | * @dev: The KSZ device instance. |
734 | * @port: The port number to be read. |
735 | * @val: The value read from the SMI interface. |
736 | * |
737 | * This function reads the SMI interface and translates the hardware register |
738 | * bit values into their corresponding control settings for a MIIM PHY Basic |
739 | * mode control register. |
740 | * |
741 | * MIIM Bit Mapping Comparison between KSZ8794 and KSZ8873 |
742 | * ------------------------------------------------------------------- |
743 | * MIIM Bit | KSZ8794 Reg/Bit | KSZ8873 Reg/Bit |
744 | * ----------------------------+-----------------------------+---------------- |
745 | * Bit 15 - Soft Reset | 0xF/4 | Not supported |
746 | * Bit 14 - Loopback | 0xD/0 (MAC), 0xF/7 (PHY) ~ 0xD/0 (PHY) |
747 | * Bit 13 - Force 100 | 0xC/6 = 0xC/6 |
748 | * Bit 12 - AN Enable | 0xC/7 (reverse logic) ~ 0xC/7 |
749 | * Bit 11 - Power Down | 0xD/3 = 0xD/3 |
750 | * Bit 10 - PHY Isolate | 0xF/5 | Not supported |
751 | * Bit 9 - Restart AN | 0xD/5 = 0xD/5 |
752 | * Bit 8 - Force Full-Duplex | 0xC/5 = 0xC/5 |
753 | * Bit 7 - Collision Test/Res. | Not supported | Not supported |
754 | * Bit 6 - Reserved | Not supported | Not supported |
755 | * Bit 5 - Hp_mdix | 0x9/7 ~ 0xF/7 |
756 | * Bit 4 - Force MDI | 0xD/1 = 0xD/1 |
757 | * Bit 3 - Disable MDIX | 0xD/2 = 0xD/2 |
758 | * Bit 2 - Disable Far-End F. | ???? | 0xD/4 |
759 | * Bit 1 - Disable Transmit | 0xD/6 = 0xD/6 |
760 | * Bit 0 - Disable LED | 0xD/7 = 0xD/7 |
761 | * ------------------------------------------------------------------- |
762 | * |
763 | * Return: 0 on success, error code on failure. |
764 | */ |
765 | static int ksz8_r_phy_bmcr(struct ksz_device *dev, u16 port, u16 *val) |
766 | { |
767 | const u16 *regs = dev->info->regs; |
768 | u8 restart, speed, ctrl; |
769 | int ret; |
770 | |
771 | *val = 0; |
772 | |
773 | ret = ksz_pread8(dev, port, offset: regs[P_NEG_RESTART_CTRL], data: &restart); |
774 | if (ret) |
775 | return ret; |
776 | |
777 | ret = ksz_pread8(dev, port, offset: regs[P_SPEED_STATUS], data: &speed); |
778 | if (ret) |
779 | return ret; |
780 | |
781 | ret = ksz_pread8(dev, port, offset: regs[P_FORCE_CTRL], data: &ctrl); |
782 | if (ret) |
783 | return ret; |
784 | |
785 | if (ctrl & PORT_FORCE_100_MBIT) |
786 | *val |= BMCR_SPEED100; |
787 | |
788 | if (ksz_is_ksz88x3(dev)) { |
789 | if (restart & KSZ8873_PORT_PHY_LOOPBACK) |
790 | *val |= BMCR_LOOPBACK; |
791 | |
792 | if ((ctrl & PORT_AUTO_NEG_ENABLE)) |
793 | *val |= BMCR_ANENABLE; |
794 | } else { |
795 | ret = ksz879x_get_loopback(dev, port, val); |
796 | if (ret) |
797 | return ret; |
798 | |
799 | if (!(ctrl & PORT_AUTO_NEG_DISABLE)) |
800 | *val |= BMCR_ANENABLE; |
801 | } |
802 | |
803 | if (restart & PORT_POWER_DOWN) |
804 | *val |= BMCR_PDOWN; |
805 | |
806 | if (restart & PORT_AUTO_NEG_RESTART) |
807 | *val |= BMCR_ANRESTART; |
808 | |
809 | if (ctrl & PORT_FORCE_FULL_DUPLEX) |
810 | *val |= BMCR_FULLDPLX; |
811 | |
812 | if (speed & PORT_HP_MDIX) |
813 | *val |= KSZ886X_BMCR_HP_MDIX; |
814 | |
815 | if (restart & PORT_FORCE_MDIX) |
816 | *val |= KSZ886X_BMCR_FORCE_MDI; |
817 | |
818 | if (restart & PORT_AUTO_MDIX_DISABLE) |
819 | *val |= KSZ886X_BMCR_DISABLE_AUTO_MDIX; |
820 | |
821 | if (restart & PORT_TX_DISABLE) |
822 | *val |= KSZ886X_BMCR_DISABLE_TRANSMIT; |
823 | |
824 | if (restart & PORT_LED_OFF) |
825 | *val |= KSZ886X_BMCR_DISABLE_LED; |
826 | |
827 | return 0; |
828 | } |
829 | |
830 | int ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val) |
831 | { |
832 | u8 ctrl, link, val1, val2; |
833 | int processed = true; |
834 | const u16 *regs; |
835 | u16 data = 0; |
836 | u16 p = phy; |
837 | int ret; |
838 | |
839 | regs = dev->info->regs; |
840 | |
841 | switch (reg) { |
842 | case MII_BMCR: |
843 | ret = ksz8_r_phy_bmcr(dev, port: p, val: &data); |
844 | if (ret) |
845 | return ret; |
846 | break; |
847 | case MII_BMSR: |
848 | ret = ksz_pread8(dev, port: p, offset: regs[P_LINK_STATUS], data: &link); |
849 | if (ret) |
850 | return ret; |
851 | |
852 | data = BMSR_100FULL | |
853 | BMSR_100HALF | |
854 | BMSR_10FULL | |
855 | BMSR_10HALF | |
856 | BMSR_ANEGCAPABLE; |
857 | if (link & PORT_AUTO_NEG_COMPLETE) |
858 | data |= BMSR_ANEGCOMPLETE; |
859 | if (link & PORT_STAT_LINK_GOOD) |
860 | data |= BMSR_LSTATUS; |
861 | break; |
862 | case MII_PHYSID1: |
863 | data = KSZ8795_ID_HI; |
864 | break; |
865 | case MII_PHYSID2: |
866 | if (ksz_is_ksz88x3(dev)) |
867 | data = KSZ8863_ID_LO; |
868 | else |
869 | data = KSZ8795_ID_LO; |
870 | break; |
871 | case MII_ADVERTISE: |
872 | ret = ksz_pread8(dev, port: p, offset: regs[P_LOCAL_CTRL], data: &ctrl); |
873 | if (ret) |
874 | return ret; |
875 | |
876 | data = ADVERTISE_CSMA; |
877 | if (ctrl & PORT_AUTO_NEG_SYM_PAUSE) |
878 | data |= ADVERTISE_PAUSE_CAP; |
879 | if (ctrl & PORT_AUTO_NEG_100BTX_FD) |
880 | data |= ADVERTISE_100FULL; |
881 | if (ctrl & PORT_AUTO_NEG_100BTX) |
882 | data |= ADVERTISE_100HALF; |
883 | if (ctrl & PORT_AUTO_NEG_10BT_FD) |
884 | data |= ADVERTISE_10FULL; |
885 | if (ctrl & PORT_AUTO_NEG_10BT) |
886 | data |= ADVERTISE_10HALF; |
887 | break; |
888 | case MII_LPA: |
889 | ret = ksz_pread8(dev, port: p, offset: regs[P_REMOTE_STATUS], data: &link); |
890 | if (ret) |
891 | return ret; |
892 | |
893 | data = LPA_SLCT; |
894 | if (link & PORT_REMOTE_SYM_PAUSE) |
895 | data |= LPA_PAUSE_CAP; |
896 | if (link & PORT_REMOTE_100BTX_FD) |
897 | data |= LPA_100FULL; |
898 | if (link & PORT_REMOTE_100BTX) |
899 | data |= LPA_100HALF; |
900 | if (link & PORT_REMOTE_10BT_FD) |
901 | data |= LPA_10FULL; |
902 | if (link & PORT_REMOTE_10BT) |
903 | data |= LPA_10HALF; |
904 | if (data & ~LPA_SLCT) |
905 | data |= LPA_LPACK; |
906 | break; |
907 | case PHY_REG_LINK_MD: |
908 | ret = ksz_pread8(dev, port: p, REG_PORT_LINK_MD_CTRL, data: &val1); |
909 | if (ret) |
910 | return ret; |
911 | |
912 | ret = ksz_pread8(dev, port: p, REG_PORT_LINK_MD_RESULT, data: &val2); |
913 | if (ret) |
914 | return ret; |
915 | |
916 | if (val1 & PORT_START_CABLE_DIAG) |
917 | data |= PHY_START_CABLE_DIAG; |
918 | |
919 | if (val1 & PORT_CABLE_10M_SHORT) |
920 | data |= PHY_CABLE_10M_SHORT; |
921 | |
922 | data |= FIELD_PREP(PHY_CABLE_DIAG_RESULT_M, |
923 | FIELD_GET(PORT_CABLE_DIAG_RESULT_M, val1)); |
924 | |
925 | data |= FIELD_PREP(PHY_CABLE_FAULT_COUNTER_M, |
926 | (FIELD_GET(PORT_CABLE_FAULT_COUNTER_H, val1) << 8) | |
927 | FIELD_GET(PORT_CABLE_FAULT_COUNTER_L, val2)); |
928 | break; |
929 | case PHY_REG_PHY_CTRL: |
930 | ret = ksz8_r_phy_ctrl(dev, port: p, val: &data); |
931 | if (ret) |
932 | return ret; |
933 | |
934 | break; |
935 | default: |
936 | processed = false; |
937 | break; |
938 | } |
939 | if (processed) |
940 | *val = data; |
941 | |
942 | return 0; |
943 | } |
944 | |
945 | /** |
946 | * ksz8_w_phy_ctrl - Translates and writes to the SMI interface from a MIIM PHY |
947 | * Control register (Reg. 31). |
948 | * @dev: The KSZ device instance. |
949 | * @port: The port number to be configured. |
950 | * @val: The register value to be written. |
951 | * |
952 | * This function translates control settings from a MIIM PHY Control register |
953 | * into their corresponding hardware register bit values for the SMI |
954 | * interface. |
955 | * |
956 | * Return: 0 on success, error code on failure. |
957 | */ |
958 | static int ksz8_w_phy_ctrl(struct ksz_device *dev, int port, u16 val) |
959 | { |
960 | u8 reg_val = 0; |
961 | int ret; |
962 | |
963 | if (val & KSZ886X_CTRL_FORCE_LINK) |
964 | reg_val |= PORT_FORCE_LINK; |
965 | |
966 | if (val & KSZ886X_CTRL_PWRSAVE) |
967 | reg_val |= PORT_POWER_SAVING; |
968 | |
969 | if (val & KSZ886X_CTRL_REMOTE_LOOPBACK) |
970 | reg_val |= PORT_PHY_REMOTE_LOOPBACK; |
971 | |
972 | ret = ksz_prmw8(dev, port, REG_PORT_LINK_MD_CTRL, PORT_FORCE_LINK | |
973 | PORT_POWER_SAVING | PORT_PHY_REMOTE_LOOPBACK, val: reg_val); |
974 | return ret; |
975 | } |
976 | |
977 | /** |
978 | * ksz8_w_phy_bmcr - Translates and writes to the SMI interface from a MIIM PHY |
979 | * Basic mode control register (Reg. 0). |
980 | * @dev: The KSZ device instance. |
981 | * @port: The port number to be configured. |
982 | * @val: The register value to be written. |
983 | * |
984 | * This function translates control settings from a MIIM PHY Basic mode control |
985 | * register into their corresponding hardware register bit values for the SMI |
986 | * interface. |
987 | * |
988 | * MIIM Bit Mapping Comparison between KSZ8794 and KSZ8873 |
989 | * ------------------------------------------------------------------- |
990 | * MIIM Bit | KSZ8794 Reg/Bit | KSZ8873 Reg/Bit |
991 | * ----------------------------+-----------------------------+---------------- |
992 | * Bit 15 - Soft Reset | 0xF/4 | Not supported |
993 | * Bit 14 - Loopback | 0xD/0 (MAC), 0xF/7 (PHY) ~ 0xD/0 (PHY) |
994 | * Bit 13 - Force 100 | 0xC/6 = 0xC/6 |
995 | * Bit 12 - AN Enable | 0xC/7 (reverse logic) ~ 0xC/7 |
996 | * Bit 11 - Power Down | 0xD/3 = 0xD/3 |
997 | * Bit 10 - PHY Isolate | 0xF/5 | Not supported |
998 | * Bit 9 - Restart AN | 0xD/5 = 0xD/5 |
999 | * Bit 8 - Force Full-Duplex | 0xC/5 = 0xC/5 |
1000 | * Bit 7 - Collision Test/Res. | Not supported | Not supported |
1001 | * Bit 6 - Reserved | Not supported | Not supported |
1002 | * Bit 5 - Hp_mdix | 0x9/7 ~ 0xF/7 |
1003 | * Bit 4 - Force MDI | 0xD/1 = 0xD/1 |
1004 | * Bit 3 - Disable MDIX | 0xD/2 = 0xD/2 |
1005 | * Bit 2 - Disable Far-End F. | ???? | 0xD/4 |
1006 | * Bit 1 - Disable Transmit | 0xD/6 = 0xD/6 |
1007 | * Bit 0 - Disable LED | 0xD/7 = 0xD/7 |
1008 | * ------------------------------------------------------------------- |
1009 | * |
1010 | * Return: 0 on success, error code on failure. |
1011 | */ |
1012 | static int ksz8_w_phy_bmcr(struct ksz_device *dev, u16 port, u16 val) |
1013 | { |
1014 | u8 restart, speed, ctrl, restart_mask; |
1015 | const u16 *regs = dev->info->regs; |
1016 | int ret; |
1017 | |
1018 | /* Do not support PHY reset function. */ |
1019 | if (val & BMCR_RESET) |
1020 | return 0; |
1021 | |
1022 | speed = 0; |
1023 | if (val & KSZ886X_BMCR_HP_MDIX) |
1024 | speed |= PORT_HP_MDIX; |
1025 | |
1026 | ret = ksz_prmw8(dev, port, offset: regs[P_SPEED_STATUS], PORT_HP_MDIX, val: speed); |
1027 | if (ret) |
1028 | return ret; |
1029 | |
1030 | ctrl = 0; |
1031 | if (ksz_is_ksz88x3(dev)) { |
1032 | if ((val & BMCR_ANENABLE)) |
1033 | ctrl |= PORT_AUTO_NEG_ENABLE; |
1034 | } else { |
1035 | if (!(val & BMCR_ANENABLE)) |
1036 | ctrl |= PORT_AUTO_NEG_DISABLE; |
1037 | |
1038 | /* Fiber port does not support auto-negotiation. */ |
1039 | if (dev->ports[port].fiber) |
1040 | ctrl |= PORT_AUTO_NEG_DISABLE; |
1041 | } |
1042 | |
1043 | if (val & BMCR_SPEED100) |
1044 | ctrl |= PORT_FORCE_100_MBIT; |
1045 | |
1046 | if (val & BMCR_FULLDPLX) |
1047 | ctrl |= PORT_FORCE_FULL_DUPLEX; |
1048 | |
1049 | ret = ksz_prmw8(dev, port, offset: regs[P_FORCE_CTRL], PORT_FORCE_100_MBIT | |
1050 | /* PORT_AUTO_NEG_ENABLE and PORT_AUTO_NEG_DISABLE are the same |
1051 | * bits |
1052 | */ |
1053 | PORT_FORCE_FULL_DUPLEX | PORT_AUTO_NEG_ENABLE, val: ctrl); |
1054 | if (ret) |
1055 | return ret; |
1056 | |
1057 | restart = 0; |
1058 | restart_mask = PORT_LED_OFF | PORT_TX_DISABLE | PORT_AUTO_NEG_RESTART | |
1059 | PORT_POWER_DOWN | PORT_AUTO_MDIX_DISABLE | PORT_FORCE_MDIX; |
1060 | |
1061 | if (val & KSZ886X_BMCR_DISABLE_LED) |
1062 | restart |= PORT_LED_OFF; |
1063 | |
1064 | if (val & KSZ886X_BMCR_DISABLE_TRANSMIT) |
1065 | restart |= PORT_TX_DISABLE; |
1066 | |
1067 | if (val & BMCR_ANRESTART) |
1068 | restart |= PORT_AUTO_NEG_RESTART; |
1069 | |
1070 | if (val & BMCR_PDOWN) |
1071 | restart |= PORT_POWER_DOWN; |
1072 | |
1073 | if (val & KSZ886X_BMCR_DISABLE_AUTO_MDIX) |
1074 | restart |= PORT_AUTO_MDIX_DISABLE; |
1075 | |
1076 | if (val & KSZ886X_BMCR_FORCE_MDI) |
1077 | restart |= PORT_FORCE_MDIX; |
1078 | |
1079 | if (ksz_is_ksz88x3(dev)) { |
1080 | restart_mask |= KSZ8873_PORT_PHY_LOOPBACK; |
1081 | |
1082 | if (val & BMCR_LOOPBACK) |
1083 | restart |= KSZ8873_PORT_PHY_LOOPBACK; |
1084 | } else { |
1085 | ret = ksz879x_set_loopback(dev, port, val); |
1086 | if (ret) |
1087 | return ret; |
1088 | } |
1089 | |
1090 | return ksz_prmw8(dev, port, offset: regs[P_NEG_RESTART_CTRL], mask: restart_mask, |
1091 | val: restart); |
1092 | } |
1093 | |
1094 | int ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val) |
1095 | { |
1096 | const u16 *regs; |
1097 | u8 ctrl, data; |
1098 | u16 p = phy; |
1099 | int ret; |
1100 | |
1101 | regs = dev->info->regs; |
1102 | |
1103 | switch (reg) { |
1104 | case MII_BMCR: |
1105 | ret = ksz8_w_phy_bmcr(dev, port: p, val); |
1106 | if (ret) |
1107 | return ret; |
1108 | break; |
1109 | case MII_ADVERTISE: |
1110 | ret = ksz_pread8(dev, port: p, offset: regs[P_LOCAL_CTRL], data: &ctrl); |
1111 | if (ret) |
1112 | return ret; |
1113 | |
1114 | data = ctrl; |
1115 | data &= ~(PORT_AUTO_NEG_SYM_PAUSE | |
1116 | PORT_AUTO_NEG_100BTX_FD | |
1117 | PORT_AUTO_NEG_100BTX | |
1118 | PORT_AUTO_NEG_10BT_FD | |
1119 | PORT_AUTO_NEG_10BT); |
1120 | if (val & ADVERTISE_PAUSE_CAP) |
1121 | data |= PORT_AUTO_NEG_SYM_PAUSE; |
1122 | if (val & ADVERTISE_100FULL) |
1123 | data |= PORT_AUTO_NEG_100BTX_FD; |
1124 | if (val & ADVERTISE_100HALF) |
1125 | data |= PORT_AUTO_NEG_100BTX; |
1126 | if (val & ADVERTISE_10FULL) |
1127 | data |= PORT_AUTO_NEG_10BT_FD; |
1128 | if (val & ADVERTISE_10HALF) |
1129 | data |= PORT_AUTO_NEG_10BT; |
1130 | |
1131 | if (data != ctrl) { |
1132 | ret = ksz_pwrite8(dev, port: p, offset: regs[P_LOCAL_CTRL], data); |
1133 | if (ret) |
1134 | return ret; |
1135 | } |
1136 | break; |
1137 | case PHY_REG_LINK_MD: |
1138 | if (val & PHY_START_CABLE_DIAG) |
1139 | ksz_port_cfg(dev, port: p, REG_PORT_LINK_MD_CTRL, PORT_START_CABLE_DIAG, set: true); |
1140 | break; |
1141 | |
1142 | case PHY_REG_PHY_CTRL: |
1143 | ret = ksz8_w_phy_ctrl(dev, port: p, val); |
1144 | if (ret) |
1145 | return ret; |
1146 | break; |
1147 | default: |
1148 | break; |
1149 | } |
1150 | |
1151 | return 0; |
1152 | } |
1153 | |
1154 | void ksz8_cfg_port_member(struct ksz_device *dev, int port, u8 member) |
1155 | { |
1156 | u8 data; |
1157 | |
1158 | ksz_pread8(dev, port, P_MIRROR_CTRL, data: &data); |
1159 | data &= ~PORT_VLAN_MEMBERSHIP; |
1160 | data |= (member & dev->port_mask); |
1161 | ksz_pwrite8(dev, port, P_MIRROR_CTRL, data); |
1162 | } |
1163 | |
1164 | void ksz8_flush_dyn_mac_table(struct ksz_device *dev, int port) |
1165 | { |
1166 | u8 learn[DSA_MAX_PORTS]; |
1167 | int first, index, cnt; |
1168 | const u16 *regs; |
1169 | |
1170 | regs = dev->info->regs; |
1171 | |
1172 | if ((uint)port < dev->info->port_cnt) { |
1173 | first = port; |
1174 | cnt = port + 1; |
1175 | } else { |
1176 | /* Flush all ports. */ |
1177 | first = 0; |
1178 | cnt = dev->info->port_cnt; |
1179 | } |
1180 | for (index = first; index < cnt; index++) { |
1181 | ksz_pread8(dev, port: index, offset: regs[P_STP_CTRL], data: &learn[index]); |
1182 | if (!(learn[index] & PORT_LEARN_DISABLE)) |
1183 | ksz_pwrite8(dev, port: index, offset: regs[P_STP_CTRL], |
1184 | data: learn[index] | PORT_LEARN_DISABLE); |
1185 | } |
1186 | ksz_cfg(dev, S_FLUSH_TABLE_CTRL, SW_FLUSH_DYN_MAC_TABLE, set: true); |
1187 | for (index = first; index < cnt; index++) { |
1188 | if (!(learn[index] & PORT_LEARN_DISABLE)) |
1189 | ksz_pwrite8(dev, port: index, offset: regs[P_STP_CTRL], data: learn[index]); |
1190 | } |
1191 | } |
1192 | |
1193 | int ksz8_fdb_dump(struct ksz_device *dev, int port, |
1194 | dsa_fdb_dump_cb_t *cb, void *data) |
1195 | { |
1196 | int ret = 0; |
1197 | u16 i = 0; |
1198 | u16 entries = 0; |
1199 | u8 timestamp = 0; |
1200 | u8 fid; |
1201 | u8 src_port; |
1202 | u8 mac[ETH_ALEN]; |
1203 | |
1204 | do { |
1205 | ret = ksz8_r_dyn_mac_table(dev, addr: i, mac_addr: mac, fid: &fid, src_port: &src_port, |
1206 | timestamp: ×tamp, entries: &entries); |
1207 | if (!ret && port == src_port) { |
1208 | ret = cb(mac, fid, false, data); |
1209 | if (ret) |
1210 | break; |
1211 | } |
1212 | i++; |
1213 | } while (i < entries); |
1214 | if (i >= entries) |
1215 | ret = 0; |
1216 | |
1217 | return ret; |
1218 | } |
1219 | |
1220 | static int ksz8_add_sta_mac(struct ksz_device *dev, int port, |
1221 | const unsigned char *addr, u16 vid) |
1222 | { |
1223 | struct alu_struct alu; |
1224 | int index, ret; |
1225 | int empty = 0; |
1226 | |
1227 | alu.port_forward = 0; |
1228 | for (index = 0; index < dev->info->num_statics; index++) { |
1229 | bool valid; |
1230 | |
1231 | ret = ksz8_r_sta_mac_table(dev, addr: index, alu: &alu, valid: &valid); |
1232 | if (ret) |
1233 | return ret; |
1234 | if (!valid) { |
1235 | /* Remember the first empty entry. */ |
1236 | if (!empty) |
1237 | empty = index + 1; |
1238 | continue; |
1239 | } |
1240 | |
1241 | if (!memcmp(p: alu.mac, q: addr, ETH_ALEN) && alu.fid == vid) |
1242 | break; |
1243 | } |
1244 | |
1245 | /* no available entry */ |
1246 | if (index == dev->info->num_statics && !empty) |
1247 | return -ENOSPC; |
1248 | |
1249 | /* add entry */ |
1250 | if (index == dev->info->num_statics) { |
1251 | index = empty - 1; |
1252 | memset(&alu, 0, sizeof(alu)); |
1253 | memcpy(alu.mac, addr, ETH_ALEN); |
1254 | alu.is_static = true; |
1255 | } |
1256 | alu.port_forward |= BIT(port); |
1257 | if (vid) { |
1258 | alu.is_use_fid = true; |
1259 | |
1260 | /* Need a way to map VID to FID. */ |
1261 | alu.fid = vid; |
1262 | } |
1263 | |
1264 | return ksz8_w_sta_mac_table(dev, addr: index, alu: &alu); |
1265 | } |
1266 | |
1267 | static int ksz8_del_sta_mac(struct ksz_device *dev, int port, |
1268 | const unsigned char *addr, u16 vid) |
1269 | { |
1270 | struct alu_struct alu; |
1271 | int index, ret; |
1272 | |
1273 | for (index = 0; index < dev->info->num_statics; index++) { |
1274 | bool valid; |
1275 | |
1276 | ret = ksz8_r_sta_mac_table(dev, addr: index, alu: &alu, valid: &valid); |
1277 | if (ret) |
1278 | return ret; |
1279 | if (!valid) |
1280 | continue; |
1281 | |
1282 | if (!memcmp(p: alu.mac, q: addr, ETH_ALEN) && alu.fid == vid) |
1283 | break; |
1284 | } |
1285 | |
1286 | /* no available entry */ |
1287 | if (index == dev->info->num_statics) |
1288 | return 0; |
1289 | |
1290 | /* clear port */ |
1291 | alu.port_forward &= ~BIT(port); |
1292 | if (!alu.port_forward) |
1293 | alu.is_static = false; |
1294 | |
1295 | return ksz8_w_sta_mac_table(dev, addr: index, alu: &alu); |
1296 | } |
1297 | |
1298 | int ksz8_mdb_add(struct ksz_device *dev, int port, |
1299 | const struct switchdev_obj_port_mdb *mdb, struct dsa_db db) |
1300 | { |
1301 | return ksz8_add_sta_mac(dev, port, addr: mdb->addr, vid: mdb->vid); |
1302 | } |
1303 | |
1304 | int ksz8_mdb_del(struct ksz_device *dev, int port, |
1305 | const struct switchdev_obj_port_mdb *mdb, struct dsa_db db) |
1306 | { |
1307 | return ksz8_del_sta_mac(dev, port, addr: mdb->addr, vid: mdb->vid); |
1308 | } |
1309 | |
1310 | int ksz8_fdb_add(struct ksz_device *dev, int port, const unsigned char *addr, |
1311 | u16 vid, struct dsa_db db) |
1312 | { |
1313 | return ksz8_add_sta_mac(dev, port, addr, vid); |
1314 | } |
1315 | |
1316 | int ksz8_fdb_del(struct ksz_device *dev, int port, const unsigned char *addr, |
1317 | u16 vid, struct dsa_db db) |
1318 | { |
1319 | return ksz8_del_sta_mac(dev, port, addr, vid); |
1320 | } |
1321 | |
1322 | int ksz8_port_vlan_filtering(struct ksz_device *dev, int port, bool flag, |
1323 | struct netlink_ext_ack *extack) |
1324 | { |
1325 | if (ksz_is_ksz88x3(dev)) |
1326 | return -ENOTSUPP; |
1327 | |
1328 | /* Discard packets with VID not enabled on the switch */ |
1329 | ksz_cfg(dev, S_MIRROR_CTRL, SW_VLAN_ENABLE, set: flag); |
1330 | |
1331 | /* Discard packets with VID not enabled on the ingress port */ |
1332 | for (port = 0; port < dev->phy_port_cnt; ++port) |
1333 | ksz_port_cfg(dev, port, REG_PORT_CTRL_2, PORT_INGRESS_FILTER, |
1334 | set: flag); |
1335 | |
1336 | return 0; |
1337 | } |
1338 | |
1339 | static void ksz8_port_enable_pvid(struct ksz_device *dev, int port, bool state) |
1340 | { |
1341 | if (ksz_is_ksz88x3(dev)) { |
1342 | ksz_cfg(dev, REG_SW_INSERT_SRC_PVID, |
1343 | bits: 0x03 << (4 - 2 * port), set: state); |
1344 | } else { |
1345 | ksz_pwrite8(dev, port, REG_PORT_CTRL_12, data: state ? 0x0f : 0x00); |
1346 | } |
1347 | } |
1348 | |
1349 | int ksz8_port_vlan_add(struct ksz_device *dev, int port, |
1350 | const struct switchdev_obj_port_vlan *vlan, |
1351 | struct netlink_ext_ack *extack) |
1352 | { |
1353 | bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED; |
1354 | struct ksz_port *p = &dev->ports[port]; |
1355 | u16 data, new_pvid = 0; |
1356 | u8 fid, member, valid; |
1357 | |
1358 | if (ksz_is_ksz88x3(dev)) |
1359 | return -ENOTSUPP; |
1360 | |
1361 | /* If a VLAN is added with untagged flag different from the |
1362 | * port's Remove Tag flag, we need to change the latter. |
1363 | * Ignore VID 0, which is always untagged. |
1364 | * Ignore CPU port, which will always be tagged. |
1365 | */ |
1366 | if (untagged != p->remove_tag && vlan->vid != 0 && |
1367 | port != dev->cpu_port) { |
1368 | unsigned int vid; |
1369 | |
1370 | /* Reject attempts to add a VLAN that requires the |
1371 | * Remove Tag flag to be changed, unless there are no |
1372 | * other VLANs currently configured. |
1373 | */ |
1374 | for (vid = 1; vid < dev->info->num_vlans; ++vid) { |
1375 | /* Skip the VID we are going to add or reconfigure */ |
1376 | if (vid == vlan->vid) |
1377 | continue; |
1378 | |
1379 | ksz8_from_vlan(dev, vlan: dev->vlan_cache[vid].table[0], |
1380 | fid: &fid, member: &member, valid: &valid); |
1381 | if (valid && (member & BIT(port))) |
1382 | return -EINVAL; |
1383 | } |
1384 | |
1385 | ksz_port_cfg(dev, port, P_TAG_CTRL, PORT_REMOVE_TAG, set: untagged); |
1386 | p->remove_tag = untagged; |
1387 | } |
1388 | |
1389 | ksz8_r_vlan_table(dev, vid: vlan->vid, vlan: &data); |
1390 | ksz8_from_vlan(dev, vlan: data, fid: &fid, member: &member, valid: &valid); |
1391 | |
1392 | /* First time to setup the VLAN entry. */ |
1393 | if (!valid) { |
1394 | /* Need to find a way to map VID to FID. */ |
1395 | fid = 1; |
1396 | valid = 1; |
1397 | } |
1398 | member |= BIT(port); |
1399 | |
1400 | ksz8_to_vlan(dev, fid, member, valid, vlan: &data); |
1401 | ksz8_w_vlan_table(dev, vid: vlan->vid, vlan: data); |
1402 | |
1403 | /* change PVID */ |
1404 | if (vlan->flags & BRIDGE_VLAN_INFO_PVID) |
1405 | new_pvid = vlan->vid; |
1406 | |
1407 | if (new_pvid) { |
1408 | u16 vid; |
1409 | |
1410 | ksz_pread16(dev, port, REG_PORT_CTRL_VID, data: &vid); |
1411 | vid &= ~VLAN_VID_MASK; |
1412 | vid |= new_pvid; |
1413 | ksz_pwrite16(dev, port, REG_PORT_CTRL_VID, data: vid); |
1414 | |
1415 | ksz8_port_enable_pvid(dev, port, state: true); |
1416 | } |
1417 | |
1418 | return 0; |
1419 | } |
1420 | |
1421 | int ksz8_port_vlan_del(struct ksz_device *dev, int port, |
1422 | const struct switchdev_obj_port_vlan *vlan) |
1423 | { |
1424 | u16 data, pvid; |
1425 | u8 fid, member, valid; |
1426 | |
1427 | if (ksz_is_ksz88x3(dev)) |
1428 | return -ENOTSUPP; |
1429 | |
1430 | ksz_pread16(dev, port, REG_PORT_CTRL_VID, data: &pvid); |
1431 | pvid = pvid & 0xFFF; |
1432 | |
1433 | ksz8_r_vlan_table(dev, vid: vlan->vid, vlan: &data); |
1434 | ksz8_from_vlan(dev, vlan: data, fid: &fid, member: &member, valid: &valid); |
1435 | |
1436 | member &= ~BIT(port); |
1437 | |
1438 | /* Invalidate the entry if no more member. */ |
1439 | if (!member) { |
1440 | fid = 0; |
1441 | valid = 0; |
1442 | } |
1443 | |
1444 | ksz8_to_vlan(dev, fid, member, valid, vlan: &data); |
1445 | ksz8_w_vlan_table(dev, vid: vlan->vid, vlan: data); |
1446 | |
1447 | if (pvid == vlan->vid) |
1448 | ksz8_port_enable_pvid(dev, port, state: false); |
1449 | |
1450 | return 0; |
1451 | } |
1452 | |
1453 | int ksz8_port_mirror_add(struct ksz_device *dev, int port, |
1454 | struct dsa_mall_mirror_tc_entry *mirror, |
1455 | bool ingress, struct netlink_ext_ack *extack) |
1456 | { |
1457 | if (ingress) { |
1458 | ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_RX, set: true); |
1459 | dev->mirror_rx |= BIT(port); |
1460 | } else { |
1461 | ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_TX, set: true); |
1462 | dev->mirror_tx |= BIT(port); |
1463 | } |
1464 | |
1465 | ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_SNIFFER, set: false); |
1466 | |
1467 | /* configure mirror port */ |
1468 | if (dev->mirror_rx || dev->mirror_tx) |
1469 | ksz_port_cfg(dev, port: mirror->to_local_port, P_MIRROR_CTRL, |
1470 | PORT_MIRROR_SNIFFER, set: true); |
1471 | |
1472 | return 0; |
1473 | } |
1474 | |
1475 | void ksz8_port_mirror_del(struct ksz_device *dev, int port, |
1476 | struct dsa_mall_mirror_tc_entry *mirror) |
1477 | { |
1478 | u8 data; |
1479 | |
1480 | if (mirror->ingress) { |
1481 | ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_RX, set: false); |
1482 | dev->mirror_rx &= ~BIT(port); |
1483 | } else { |
1484 | ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_TX, set: false); |
1485 | dev->mirror_tx &= ~BIT(port); |
1486 | } |
1487 | |
1488 | ksz_pread8(dev, port, P_MIRROR_CTRL, data: &data); |
1489 | |
1490 | if (!dev->mirror_rx && !dev->mirror_tx) |
1491 | ksz_port_cfg(dev, port: mirror->to_local_port, P_MIRROR_CTRL, |
1492 | PORT_MIRROR_SNIFFER, set: false); |
1493 | } |
1494 | |
1495 | static void ksz8795_cpu_interface_select(struct ksz_device *dev, int port) |
1496 | { |
1497 | struct ksz_port *p = &dev->ports[port]; |
1498 | |
1499 | if (!ksz_is_ksz87xx(dev)) |
1500 | return; |
1501 | |
1502 | if (!p->interface && dev->compat_interface) { |
1503 | dev_warn(dev->dev, |
1504 | "Using legacy switch \"phy-mode\" property, because it is missing on port %d node. " |
1505 | "Please update your device tree.\n" , |
1506 | port); |
1507 | p->interface = dev->compat_interface; |
1508 | } |
1509 | } |
1510 | |
1511 | void ksz8_port_setup(struct ksz_device *dev, int port, bool cpu_port) |
1512 | { |
1513 | struct dsa_switch *ds = dev->ds; |
1514 | const u32 *masks; |
1515 | u8 member; |
1516 | |
1517 | masks = dev->info->masks; |
1518 | |
1519 | /* enable broadcast storm limit */ |
1520 | ksz_port_cfg(dev, port, P_BCAST_STORM_CTRL, PORT_BROADCAST_STORM, set: true); |
1521 | |
1522 | if (!ksz_is_ksz88x3(dev)) |
1523 | ksz8795_set_prio_queue(dev, port, queue: 4); |
1524 | |
1525 | /* disable DiffServ priority */ |
1526 | ksz_port_cfg(dev, port, P_PRIO_CTRL, PORT_DIFFSERV_ENABLE, set: false); |
1527 | |
1528 | /* replace priority */ |
1529 | ksz_port_cfg(dev, port, P_802_1P_CTRL, |
1530 | bits: masks[PORT_802_1P_REMAPPING], set: false); |
1531 | |
1532 | /* enable 802.1p priority */ |
1533 | ksz_port_cfg(dev, port, P_PRIO_CTRL, PORT_802_1P_ENABLE, set: true); |
1534 | |
1535 | if (cpu_port) |
1536 | member = dsa_user_ports(ds); |
1537 | else |
1538 | member = BIT(dsa_upstream_port(ds, port)); |
1539 | |
1540 | ksz8_cfg_port_member(dev, port, member); |
1541 | } |
1542 | |
1543 | static void ksz88x3_config_rmii_clk(struct ksz_device *dev) |
1544 | { |
1545 | struct dsa_port *cpu_dp = dsa_to_port(ds: dev->ds, p: dev->cpu_port); |
1546 | bool rmii_clk_internal; |
1547 | |
1548 | if (!ksz_is_ksz88x3(dev)) |
1549 | return; |
1550 | |
1551 | rmii_clk_internal = of_property_read_bool(np: cpu_dp->dn, |
1552 | propname: "microchip,rmii-clk-internal" ); |
1553 | |
1554 | ksz_cfg(dev, KSZ88X3_REG_FVID_AND_HOST_MODE, |
1555 | KSZ88X3_PORT3_RMII_CLK_INTERNAL, set: rmii_clk_internal); |
1556 | } |
1557 | |
1558 | void ksz8_config_cpu_port(struct dsa_switch *ds) |
1559 | { |
1560 | struct ksz_device *dev = ds->priv; |
1561 | struct ksz_port *p; |
1562 | const u32 *masks; |
1563 | const u16 *regs; |
1564 | u8 remote; |
1565 | int i; |
1566 | |
1567 | masks = dev->info->masks; |
1568 | regs = dev->info->regs; |
1569 | |
1570 | ksz_cfg(dev, addr: regs[S_TAIL_TAG_CTRL], bits: masks[SW_TAIL_TAG_ENABLE], set: true); |
1571 | |
1572 | ksz8_port_setup(dev, port: dev->cpu_port, cpu_port: true); |
1573 | |
1574 | ksz8795_cpu_interface_select(dev, port: dev->cpu_port); |
1575 | ksz88x3_config_rmii_clk(dev); |
1576 | |
1577 | for (i = 0; i < dev->phy_port_cnt; i++) { |
1578 | ksz_port_stp_state_set(ds, port: i, BR_STATE_DISABLED); |
1579 | } |
1580 | for (i = 0; i < dev->phy_port_cnt; i++) { |
1581 | p = &dev->ports[i]; |
1582 | |
1583 | if (!ksz_is_ksz88x3(dev)) { |
1584 | ksz_pread8(dev, port: i, offset: regs[P_REMOTE_STATUS], data: &remote); |
1585 | if (remote & KSZ8_PORT_FIBER_MODE) |
1586 | p->fiber = 1; |
1587 | } |
1588 | if (p->fiber) |
1589 | ksz_port_cfg(dev, port: i, offset: regs[P_STP_CTRL], |
1590 | PORT_FORCE_FLOW_CTRL, set: true); |
1591 | else |
1592 | ksz_port_cfg(dev, port: i, offset: regs[P_STP_CTRL], |
1593 | PORT_FORCE_FLOW_CTRL, set: false); |
1594 | } |
1595 | } |
1596 | |
1597 | /** |
1598 | * ksz8_phy_port_link_up - Configures ports with integrated PHYs |
1599 | * @dev: The KSZ device instance. |
1600 | * @port: The port number to configure. |
1601 | * @duplex: The desired duplex mode. |
1602 | * @tx_pause: If true, enables transmit pause. |
1603 | * @rx_pause: If true, enables receive pause. |
1604 | * |
1605 | * Description: |
1606 | * The function configures flow control settings for a given port based on the |
1607 | * desired settings and current duplex mode. |
1608 | * |
1609 | * According to the KSZ8873 datasheet, the PORT_FORCE_FLOW_CTRL bit in the |
1610 | * Port Control 2 register (0x1A for Port 1, 0x22 for Port 2, 0x32 for Port 3) |
1611 | * determines how flow control is handled on the port: |
1612 | * "1 = will always enable full-duplex flow control on the port, regardless |
1613 | * of AN result. |
1614 | * 0 = full-duplex flow control is enabled based on AN result." |
1615 | * |
1616 | * This means that the flow control behavior depends on the state of this bit: |
1617 | * - If PORT_FORCE_FLOW_CTRL is set to 1, the switch will ignore AN results and |
1618 | * force flow control on the port. |
1619 | * - If PORT_FORCE_FLOW_CTRL is set to 0, the switch will enable or disable |
1620 | * flow control based on the AN results. |
1621 | * |
1622 | * However, there is a potential limitation in this configuration. It is |
1623 | * currently not possible to force disable flow control on a port if we still |
1624 | * advertise pause support. While such a configuration is not currently |
1625 | * supported by Linux, and may not make practical sense, it's important to be |
1626 | * aware of this limitation when working with the KSZ8873 and similar devices. |
1627 | */ |
1628 | static void ksz8_phy_port_link_up(struct ksz_device *dev, int port, int duplex, |
1629 | bool tx_pause, bool rx_pause) |
1630 | { |
1631 | const u16 *regs = dev->info->regs; |
1632 | u8 sctrl = 0; |
1633 | |
1634 | /* The KSZ8795 switch differs from the KSZ8873 by supporting |
1635 | * asymmetric pause control. However, since a single bit is used to |
1636 | * control both RX and TX pause, we can't enforce asymmetric pause |
1637 | * control - both TX and RX pause will be either enabled or disabled |
1638 | * together. |
1639 | * |
1640 | * If auto-negotiation is enabled, we usually allow the flow control to |
1641 | * be determined by the auto-negotiation process based on the |
1642 | * capabilities of both link partners. However, for KSZ8873, the |
1643 | * PORT_FORCE_FLOW_CTRL bit may be set by the hardware bootstrap, |
1644 | * ignoring the auto-negotiation result. Thus, even in auto-negotiation |
1645 | * mode, we need to ensure that the PORT_FORCE_FLOW_CTRL bit is |
1646 | * properly cleared. |
1647 | * |
1648 | * In the absence of pause auto-negotiation, we will enforce symmetric |
1649 | * pause control for both variants of switches - KSZ8873 and KSZ8795. |
1650 | * |
1651 | * Autoneg Pause Autoneg rx,tx PORT_FORCE_FLOW_CTRL |
1652 | * 1 1 x 0 |
1653 | * 0 1 x 0 (flow control probably disabled) |
1654 | * x 0 1 1 (flow control force enabled) |
1655 | * 1 0 0 0 (flow control still depends on |
1656 | * aneg result due to hardware) |
1657 | * 0 0 0 0 (flow control probably disabled) |
1658 | */ |
1659 | if (dev->ports[port].manual_flow && tx_pause) |
1660 | sctrl |= PORT_FORCE_FLOW_CTRL; |
1661 | |
1662 | ksz_prmw8(dev, port, offset: regs[P_STP_CTRL], PORT_FORCE_FLOW_CTRL, val: sctrl); |
1663 | } |
1664 | |
1665 | /** |
1666 | * ksz8_cpu_port_link_up - Configures the CPU port of the switch. |
1667 | * @dev: The KSZ device instance. |
1668 | * @speed: The desired link speed. |
1669 | * @duplex: The desired duplex mode. |
1670 | * @tx_pause: If true, enables transmit pause. |
1671 | * @rx_pause: If true, enables receive pause. |
1672 | * |
1673 | * Description: |
1674 | * The function configures flow control and speed settings for the CPU |
1675 | * port of the switch based on the desired settings, current duplex mode, and |
1676 | * speed. |
1677 | */ |
1678 | static void ksz8_cpu_port_link_up(struct ksz_device *dev, int speed, int duplex, |
1679 | bool tx_pause, bool rx_pause) |
1680 | { |
1681 | const u16 *regs = dev->info->regs; |
1682 | u8 ctrl = 0; |
1683 | |
1684 | /* SW_FLOW_CTRL, SW_HALF_DUPLEX, and SW_10_MBIT bits are bootstrappable |
1685 | * at least on KSZ8873. They can have different values depending on your |
1686 | * board setup. |
1687 | */ |
1688 | if (tx_pause || rx_pause) |
1689 | ctrl |= SW_FLOW_CTRL; |
1690 | |
1691 | if (duplex == DUPLEX_HALF) |
1692 | ctrl |= SW_HALF_DUPLEX; |
1693 | |
1694 | /* This hardware only supports SPEED_10 and SPEED_100. For SPEED_10 |
1695 | * we need to set the SW_10_MBIT bit. Otherwise, we can leave it 0. |
1696 | */ |
1697 | if (speed == SPEED_10) |
1698 | ctrl |= SW_10_MBIT; |
1699 | |
1700 | ksz_rmw8(dev, offset: regs[S_BROADCAST_CTRL], SW_HALF_DUPLEX | SW_FLOW_CTRL | |
1701 | SW_10_MBIT, val: ctrl); |
1702 | } |
1703 | |
1704 | void ksz8_phylink_mac_link_up(struct ksz_device *dev, int port, |
1705 | unsigned int mode, phy_interface_t interface, |
1706 | struct phy_device *phydev, int speed, int duplex, |
1707 | bool tx_pause, bool rx_pause) |
1708 | { |
1709 | /* If the port is the CPU port, apply special handling. Only the CPU |
1710 | * port is configured via global registers. |
1711 | */ |
1712 | if (dev->cpu_port == port) |
1713 | ksz8_cpu_port_link_up(dev, speed, duplex, tx_pause, rx_pause); |
1714 | else if (dev->info->internal_phy[port]) |
1715 | ksz8_phy_port_link_up(dev, port, duplex, tx_pause, rx_pause); |
1716 | } |
1717 | |
1718 | static int ksz8_handle_global_errata(struct dsa_switch *ds) |
1719 | { |
1720 | struct ksz_device *dev = ds->priv; |
1721 | int ret = 0; |
1722 | |
1723 | /* KSZ87xx Errata DS80000687C. |
1724 | * Module 2: Link drops with some EEE link partners. |
1725 | * An issue with the EEE next page exchange between the |
1726 | * KSZ879x/KSZ877x/KSZ876x and some EEE link partners may result in |
1727 | * the link dropping. |
1728 | */ |
1729 | if (dev->info->ksz87xx_eee_link_erratum) |
1730 | ret = ksz8_ind_write8(dev, TABLE_EEE, REG_IND_EEE_GLOB2_HI, data: 0); |
1731 | |
1732 | return ret; |
1733 | } |
1734 | |
1735 | int ksz8_enable_stp_addr(struct ksz_device *dev) |
1736 | { |
1737 | struct alu_struct alu; |
1738 | |
1739 | /* Setup STP address for STP operation. */ |
1740 | memset(&alu, 0, sizeof(alu)); |
1741 | ether_addr_copy(dst: alu.mac, eth_stp_addr); |
1742 | alu.is_static = true; |
1743 | alu.is_override = true; |
1744 | alu.port_forward = dev->info->cpu_ports; |
1745 | |
1746 | return ksz8_w_sta_mac_table(dev, addr: 0, alu: &alu); |
1747 | } |
1748 | |
1749 | int ksz8_setup(struct dsa_switch *ds) |
1750 | { |
1751 | struct ksz_device *dev = ds->priv; |
1752 | int i; |
1753 | |
1754 | ds->mtu_enforcement_ingress = true; |
1755 | |
1756 | /* We rely on software untagging on the CPU port, so that we |
1757 | * can support both tagged and untagged VLANs |
1758 | */ |
1759 | ds->untag_bridge_pvid = true; |
1760 | |
1761 | /* VLAN filtering is partly controlled by the global VLAN |
1762 | * Enable flag |
1763 | */ |
1764 | ds->vlan_filtering_is_global = true; |
1765 | |
1766 | /* Enable automatic fast aging when link changed detected. */ |
1767 | ksz_cfg(dev, S_LINK_AGING_CTRL, SW_LINK_AUTO_AGING, set: true); |
1768 | |
1769 | /* Enable aggressive back off algorithm in half duplex mode. */ |
1770 | regmap_update_bits(map: ksz_regmap_8(dev), REG_SW_CTRL_1, |
1771 | SW_AGGR_BACKOFF, SW_AGGR_BACKOFF); |
1772 | |
1773 | /* |
1774 | * Make sure unicast VLAN boundary is set as default and |
1775 | * enable no excessive collision drop. |
1776 | */ |
1777 | regmap_update_bits(map: ksz_regmap_8(dev), REG_SW_CTRL_2, |
1778 | UNICAST_VLAN_BOUNDARY | NO_EXC_COLLISION_DROP, |
1779 | UNICAST_VLAN_BOUNDARY | NO_EXC_COLLISION_DROP); |
1780 | |
1781 | ksz_cfg(dev, S_REPLACE_VID_CTRL, SW_REPLACE_VID, set: false); |
1782 | |
1783 | ksz_cfg(dev, S_MIRROR_CTRL, SW_MIRROR_RX_TX, set: false); |
1784 | |
1785 | if (!ksz_is_ksz88x3(dev)) |
1786 | ksz_cfg(dev, REG_SW_CTRL_19, SW_INS_TAG_ENABLE, set: true); |
1787 | |
1788 | for (i = 0; i < (dev->info->num_vlans / 4); i++) |
1789 | ksz8_r_vlan_entries(dev, addr: i); |
1790 | |
1791 | return ksz8_handle_global_errata(ds); |
1792 | } |
1793 | |
1794 | void ksz8_get_caps(struct ksz_device *dev, int port, |
1795 | struct phylink_config *config) |
1796 | { |
1797 | config->mac_capabilities = MAC_10 | MAC_100; |
1798 | |
1799 | /* Silicon Errata Sheet (DS80000830A): |
1800 | * "Port 1 does not respond to received flow control PAUSE frames" |
1801 | * So, disable Pause support on "Port 1" (port == 0) for all ksz88x3 |
1802 | * switches. |
1803 | */ |
1804 | if (!ksz_is_ksz88x3(dev) || port) |
1805 | config->mac_capabilities |= MAC_SYM_PAUSE; |
1806 | |
1807 | /* Asym pause is not supported on KSZ8863 and KSZ8873 */ |
1808 | if (!ksz_is_ksz88x3(dev)) |
1809 | config->mac_capabilities |= MAC_ASYM_PAUSE; |
1810 | } |
1811 | |
1812 | u32 ksz8_get_port_addr(int port, int offset) |
1813 | { |
1814 | return PORT_CTRL_ADDR(port, offset); |
1815 | } |
1816 | |
1817 | int ksz8_switch_init(struct ksz_device *dev) |
1818 | { |
1819 | dev->cpu_port = fls(x: dev->info->cpu_ports) - 1; |
1820 | dev->phy_port_cnt = dev->info->port_cnt - 1; |
1821 | dev->port_mask = (BIT(dev->phy_port_cnt) - 1) | dev->info->cpu_ports; |
1822 | |
1823 | return 0; |
1824 | } |
1825 | |
1826 | void ksz8_switch_exit(struct ksz_device *dev) |
1827 | { |
1828 | ksz8_reset_switch(dev); |
1829 | } |
1830 | |
1831 | MODULE_AUTHOR("Tristram Ha <Tristram.Ha@microchip.com>" ); |
1832 | MODULE_DESCRIPTION("Microchip KSZ8795 Series Switch DSA Driver" ); |
1833 | MODULE_LICENSE("GPL" ); |
1834 | |