]> Git Repo - linux.git/blame - drivers/net/dsa/mv88e6xxx/global2.c
net: dsa: mv88e6xxx: prefix Global 2 Switch MAC macros
[linux.git] / drivers / net / dsa / mv88e6xxx / global2.c
CommitLineData
ec561276 1/*
dc30c35b
AL
2 * Marvell 88E6xxx Switch Global 2 Registers support (device address
3 * 0x1C)
ec561276
VD
4 *
5 * Copyright (c) 2008 Marvell Semiconductor
6 *
4333d619
VD
7 * Copyright (c) 2016-2017 Savoir-faire Linux Inc.
8 * Vivien Didelot <[email protected]>
ec561276
VD
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 */
15
e289ef0d 16#include <linux/bitfield.h>
282ccf6e 17#include <linux/interrupt.h>
dc30c35b 18#include <linux/irqdomain.h>
4d5f2ba7
VD
19
20#include "chip.h"
82466921 21#include "global1.h" /* for MV88E6XXX_G1_STS_IRQ_DEVICE */
ec561276
VD
22#include "global2.h"
23
9fe850fb
VD
24static int mv88e6xxx_g2_read(struct mv88e6xxx_chip *chip, int reg, u16 *val)
25{
26 return mv88e6xxx_read(chip, ADDR_GLOBAL2, reg, val);
27}
28
29static int mv88e6xxx_g2_write(struct mv88e6xxx_chip *chip, int reg, u16 val)
30{
31 return mv88e6xxx_write(chip, ADDR_GLOBAL2, reg, val);
32}
33
34static int mv88e6xxx_g2_update(struct mv88e6xxx_chip *chip, int reg, u16 update)
35{
36 return mv88e6xxx_update(chip, ADDR_GLOBAL2, reg, update);
37}
38
39static int mv88e6xxx_g2_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask)
40{
41 return mv88e6xxx_wait(chip, ADDR_GLOBAL2, reg, mask);
42}
43
6e55f698
AL
44/* Offset 0x02: Management Enable 2x */
45/* Offset 0x03: Management Enable 0x */
46
47int mv88e6095_g2_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip)
48{
49 int err;
50
51 /* Consider the frames with reserved multicast destination
52 * addresses matching 01:80:c2:00:00:2x as MGMT.
53 */
54 if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_2X)) {
6bff47be 55 err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_MGMT_EN_2X, 0xffff);
6e55f698
AL
56 if (err)
57 return err;
58 }
59
60 /* Consider the frames with reserved multicast destination
61 * addresses matching 01:80:c2:00:00:0x as MGMT.
62 */
63 if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_0X))
6bff47be
VD
64 return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_MGMT_EN_0X,
65 0xffff);
6e55f698
AL
66
67 return 0;
68}
69
ec561276
VD
70/* Offset 0x06: Device Mapping Table register */
71
72static int mv88e6xxx_g2_device_mapping_write(struct mv88e6xxx_chip *chip,
73 int target, int port)
74{
75 u16 val = (target << 8) | (port & 0xf);
76
067e474a 77 return mv88e6xxx_g2_update(chip, MV88E6XXX_G2_DEVICE_MAPPING, val);
ec561276
VD
78}
79
80static int mv88e6xxx_g2_set_device_mapping(struct mv88e6xxx_chip *chip)
81{
82 int target, port;
83 int err;
84
85 /* Initialize the routing port to the 32 possible target devices */
86 for (target = 0; target < 32; ++target) {
87 port = 0xf;
88
89 if (target < DSA_MAX_SWITCHES) {
90 port = chip->ds->rtable[target];
91 if (port == DSA_RTABLE_NONE)
92 port = 0xf;
93 }
94
95 err = mv88e6xxx_g2_device_mapping_write(chip, target, port);
96 if (err)
97 break;
98 }
99
100 return err;
101}
102
103/* Offset 0x07: Trunk Mask Table register */
104
105static int mv88e6xxx_g2_trunk_mask_write(struct mv88e6xxx_chip *chip, int num,
56dc7347 106 bool hash, u16 mask)
ec561276 107{
56dc7347 108 u16 val = (num << 12) | (mask & mv88e6xxx_port_mask(chip));
ec561276 109
56dc7347
VD
110 if (hash)
111 val |= MV88E6XXX_G2_TRUNK_MASK_HASH;
ec561276 112
56dc7347 113 return mv88e6xxx_g2_update(chip, MV88E6XXX_G2_TRUNK_MASK, val);
ec561276
VD
114}
115
116/* Offset 0x08: Trunk Mapping Table register */
117
118static int mv88e6xxx_g2_trunk_mapping_write(struct mv88e6xxx_chip *chip, int id,
119 u16 map)
120{
370b4ffb 121 const u16 port_mask = BIT(mv88e6xxx_num_ports(chip)) - 1;
ec561276
VD
122 u16 val = (id << 11) | (map & port_mask);
123
56dc7347 124 return mv88e6xxx_g2_update(chip, MV88E6XXX_G2_TRUNK_MAPPING, val);
ec561276
VD
125}
126
127static int mv88e6xxx_g2_clear_trunk(struct mv88e6xxx_chip *chip)
128{
370b4ffb 129 const u16 port_mask = BIT(mv88e6xxx_num_ports(chip)) - 1;
ec561276
VD
130 int i, err;
131
132 /* Clear all eight possible Trunk Mask vectors */
133 for (i = 0; i < 8; ++i) {
134 err = mv88e6xxx_g2_trunk_mask_write(chip, i, false, port_mask);
135 if (err)
136 return err;
137 }
138
139 /* Clear all sixteen possible Trunk ID routing vectors */
140 for (i = 0; i < 16; ++i) {
141 err = mv88e6xxx_g2_trunk_mapping_write(chip, i, 0);
142 if (err)
143 return err;
144 }
145
146 return 0;
147}
148
149/* Offset 0x09: Ingress Rate Command register
150 * Offset 0x0A: Ingress Rate Data register
151 */
152
cd8da8bb 153static int mv88e6xxx_g2_irl_wait(struct mv88e6xxx_chip *chip)
ec561276 154{
cd8da8bb
VD
155 return mv88e6xxx_g2_wait(chip, MV88E6XXX_G2_IRL_CMD,
156 MV88E6XXX_G2_IRL_CMD_BUSY);
157}
ec561276 158
cd8da8bb
VD
159static int mv88e6xxx_g2_irl_op(struct mv88e6xxx_chip *chip, u16 op, int port,
160 int res, int reg)
161{
162 int err;
ec561276 163
cd8da8bb
VD
164 err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_IRL_CMD,
165 MV88E6XXX_G2_IRL_CMD_BUSY | op | (port << 8) |
166 (res << 5) | reg);
167 if (err)
168 return err;
169
170 return mv88e6xxx_g2_irl_wait(chip);
171}
172
173int mv88e6352_g2_irl_init_all(struct mv88e6xxx_chip *chip, int port)
174{
175 return mv88e6xxx_g2_irl_op(chip, MV88E6352_G2_IRL_CMD_OP_INIT_ALL, port,
176 0, 0);
177}
178
179int mv88e6390_g2_irl_init_all(struct mv88e6xxx_chip *chip, int port)
180{
181 return mv88e6xxx_g2_irl_op(chip, MV88E6390_G2_IRL_CMD_OP_INIT_ALL, port,
182 0, 0);
ec561276
VD
183}
184
17a1594e
VD
185/* Offset 0x0B: Cross-chip Port VLAN (Addr) Register
186 * Offset 0x0C: Cross-chip Port VLAN Data Register
187 */
188
189static int mv88e6xxx_g2_pvt_op_wait(struct mv88e6xxx_chip *chip)
190{
67d1ea8e
VD
191 return mv88e6xxx_g2_wait(chip, MV88E6XXX_G2_PVT_ADDR,
192 MV88E6XXX_G2_PVT_ADDR_BUSY);
17a1594e
VD
193}
194
195static int mv88e6xxx_g2_pvt_op(struct mv88e6xxx_chip *chip, int src_dev,
196 int src_port, u16 op)
197{
198 int err;
199
67d1ea8e
VD
200 /* 9-bit Cross-chip PVT pointer: with MV88E6XXX_G2_MISC_5_BIT_PORT
201 * cleared, source device is 5-bit, source port is 4-bit.
17a1594e 202 */
67d1ea8e 203 op |= MV88E6XXX_G2_PVT_ADDR_BUSY;
17a1594e
VD
204 op |= (src_dev & 0x1f) << 4;
205 op |= (src_port & 0xf);
206
67d1ea8e 207 err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_PVT_ADDR, op);
17a1594e
VD
208 if (err)
209 return err;
210
211 return mv88e6xxx_g2_pvt_op_wait(chip);
212}
213
214int mv88e6xxx_g2_pvt_write(struct mv88e6xxx_chip *chip, int src_dev,
215 int src_port, u16 data)
216{
217 int err;
218
219 err = mv88e6xxx_g2_pvt_op_wait(chip);
220 if (err)
221 return err;
222
67d1ea8e 223 err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_PVT_DATA, data);
17a1594e
VD
224 if (err)
225 return err;
226
227 return mv88e6xxx_g2_pvt_op(chip, src_dev, src_port,
67d1ea8e 228 MV88E6XXX_G2_PVT_ADDR_OP_WRITE_PVLAN);
17a1594e
VD
229}
230
ec561276
VD
231/* Offset 0x0D: Switch MAC/WoL/WoF register */
232
233static int mv88e6xxx_g2_switch_mac_write(struct mv88e6xxx_chip *chip,
234 unsigned int pointer, u8 data)
235{
236 u16 val = (pointer << 8) | data;
237
ed44152f 238 return mv88e6xxx_g2_update(chip, MV88E6XXX_G2_SWITCH_MAC, val);
ec561276
VD
239}
240
241int mv88e6xxx_g2_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr)
242{
243 int i, err;
244
245 for (i = 0; i < 6; i++) {
246 err = mv88e6xxx_g2_switch_mac_write(chip, i, addr[i]);
247 if (err)
248 break;
249 }
250
251 return err;
252}
253
254/* Offset 0x0F: Priority Override Table */
255
256static int mv88e6xxx_g2_pot_write(struct mv88e6xxx_chip *chip, int pointer,
257 u8 data)
258{
259 u16 val = (pointer << 8) | (data & 0x7);
260
9fe850fb 261 return mv88e6xxx_g2_update(chip, GLOBAL2_PRIO_OVERRIDE, val);
ec561276
VD
262}
263
264static int mv88e6xxx_g2_clear_pot(struct mv88e6xxx_chip *chip)
265{
266 int i, err;
267
268 /* Clear all sixteen possible Priority Override entries */
269 for (i = 0; i < 16; i++) {
270 err = mv88e6xxx_g2_pot_write(chip, i, 0);
271 if (err)
272 break;
273 }
274
275 return err;
276}
277
278/* Offset 0x14: EEPROM Command
98fc3c6f
VD
279 * Offset 0x15: EEPROM Data (for 16-bit data access)
280 * Offset 0x15: EEPROM Addr (for 8-bit data access)
ec561276
VD
281 */
282
283static int mv88e6xxx_g2_eeprom_wait(struct mv88e6xxx_chip *chip)
284{
7fc8c9d5
VD
285 return mv88e6xxx_g2_wait(chip, MV88E6XXX_G2_EEPROM_CMD,
286 MV88E6XXX_G2_EEPROM_CMD_BUSY |
287 MV88E6XXX_G2_EEPROM_CMD_RUNNING);
ec561276
VD
288}
289
290static int mv88e6xxx_g2_eeprom_cmd(struct mv88e6xxx_chip *chip, u16 cmd)
291{
292 int err;
293
7fc8c9d5
VD
294 err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_EEPROM_CMD,
295 MV88E6XXX_G2_EEPROM_CMD_BUSY | cmd);
ec561276
VD
296 if (err)
297 return err;
298
299 return mv88e6xxx_g2_eeprom_wait(chip);
300}
301
98fc3c6f
VD
302static int mv88e6xxx_g2_eeprom_read8(struct mv88e6xxx_chip *chip,
303 u16 addr, u8 *data)
304{
7fc8c9d5 305 u16 cmd = MV88E6XXX_G2_EEPROM_CMD_OP_READ;
98fc3c6f
VD
306 int err;
307
308 err = mv88e6xxx_g2_eeprom_wait(chip);
309 if (err)
310 return err;
311
7fc8c9d5 312 err = mv88e6xxx_g2_write(chip, MV88E6390_G2_EEPROM_ADDR, addr);
98fc3c6f
VD
313 if (err)
314 return err;
315
316 err = mv88e6xxx_g2_eeprom_cmd(chip, cmd);
317 if (err)
318 return err;
319
7fc8c9d5 320 err = mv88e6xxx_g2_read(chip, MV88E6XXX_G2_EEPROM_CMD, &cmd);
98fc3c6f
VD
321 if (err)
322 return err;
323
324 *data = cmd & 0xff;
325
326 return 0;
327}
328
329static int mv88e6xxx_g2_eeprom_write8(struct mv88e6xxx_chip *chip,
330 u16 addr, u8 data)
331{
7fc8c9d5
VD
332 u16 cmd = MV88E6XXX_G2_EEPROM_CMD_OP_WRITE |
333 MV88E6XXX_G2_EEPROM_CMD_WRITE_EN;
98fc3c6f
VD
334 int err;
335
336 err = mv88e6xxx_g2_eeprom_wait(chip);
337 if (err)
338 return err;
339
7fc8c9d5 340 err = mv88e6xxx_g2_write(chip, MV88E6390_G2_EEPROM_ADDR, addr);
98fc3c6f
VD
341 if (err)
342 return err;
343
344 return mv88e6xxx_g2_eeprom_cmd(chip, cmd | data);
345}
346
ec561276
VD
347static int mv88e6xxx_g2_eeprom_read16(struct mv88e6xxx_chip *chip,
348 u8 addr, u16 *data)
349{
7fc8c9d5 350 u16 cmd = MV88E6XXX_G2_EEPROM_CMD_OP_READ | addr;
ec561276
VD
351 int err;
352
353 err = mv88e6xxx_g2_eeprom_wait(chip);
354 if (err)
355 return err;
356
357 err = mv88e6xxx_g2_eeprom_cmd(chip, cmd);
358 if (err)
359 return err;
360
7fc8c9d5 361 return mv88e6xxx_g2_read(chip, MV88E6352_G2_EEPROM_DATA, data);
ec561276
VD
362}
363
364static int mv88e6xxx_g2_eeprom_write16(struct mv88e6xxx_chip *chip,
365 u8 addr, u16 data)
366{
7fc8c9d5 367 u16 cmd = MV88E6XXX_G2_EEPROM_CMD_OP_WRITE | addr;
ec561276
VD
368 int err;
369
370 err = mv88e6xxx_g2_eeprom_wait(chip);
371 if (err)
372 return err;
373
7fc8c9d5 374 err = mv88e6xxx_g2_write(chip, MV88E6352_G2_EEPROM_DATA, data);
ec561276
VD
375 if (err)
376 return err;
377
378 return mv88e6xxx_g2_eeprom_cmd(chip, cmd);
379}
380
98fc3c6f
VD
381int mv88e6xxx_g2_get_eeprom8(struct mv88e6xxx_chip *chip,
382 struct ethtool_eeprom *eeprom, u8 *data)
383{
384 unsigned int offset = eeprom->offset;
385 unsigned int len = eeprom->len;
386 int err;
387
388 eeprom->len = 0;
389
390 while (len) {
391 err = mv88e6xxx_g2_eeprom_read8(chip, offset, data);
392 if (err)
393 return err;
394
395 eeprom->len++;
396 offset++;
397 data++;
398 len--;
399 }
400
401 return 0;
402}
403
404int mv88e6xxx_g2_set_eeprom8(struct mv88e6xxx_chip *chip,
405 struct ethtool_eeprom *eeprom, u8 *data)
406{
407 unsigned int offset = eeprom->offset;
408 unsigned int len = eeprom->len;
409 int err;
410
411 eeprom->len = 0;
412
413 while (len) {
414 err = mv88e6xxx_g2_eeprom_write8(chip, offset, *data);
415 if (err)
416 return err;
417
418 eeprom->len++;
419 offset++;
420 data++;
421 len--;
422 }
423
424 return 0;
425}
426
ec561276
VD
427int mv88e6xxx_g2_get_eeprom16(struct mv88e6xxx_chip *chip,
428 struct ethtool_eeprom *eeprom, u8 *data)
429{
430 unsigned int offset = eeprom->offset;
431 unsigned int len = eeprom->len;
432 u16 val;
433 int err;
434
435 eeprom->len = 0;
436
437 if (offset & 1) {
438 err = mv88e6xxx_g2_eeprom_read16(chip, offset >> 1, &val);
439 if (err)
440 return err;
441
442 *data++ = (val >> 8) & 0xff;
443
444 offset++;
445 len--;
446 eeprom->len++;
447 }
448
449 while (len >= 2) {
450 err = mv88e6xxx_g2_eeprom_read16(chip, offset >> 1, &val);
451 if (err)
452 return err;
453
454 *data++ = val & 0xff;
455 *data++ = (val >> 8) & 0xff;
456
457 offset += 2;
458 len -= 2;
459 eeprom->len += 2;
460 }
461
462 if (len) {
463 err = mv88e6xxx_g2_eeprom_read16(chip, offset >> 1, &val);
464 if (err)
465 return err;
466
467 *data++ = val & 0xff;
468
469 offset++;
470 len--;
471 eeprom->len++;
472 }
473
474 return 0;
475}
476
477int mv88e6xxx_g2_set_eeprom16(struct mv88e6xxx_chip *chip,
478 struct ethtool_eeprom *eeprom, u8 *data)
479{
480 unsigned int offset = eeprom->offset;
481 unsigned int len = eeprom->len;
482 u16 val;
483 int err;
484
485 /* Ensure the RO WriteEn bit is set */
7fc8c9d5 486 err = mv88e6xxx_g2_read(chip, MV88E6XXX_G2_EEPROM_CMD, &val);
ec561276
VD
487 if (err)
488 return err;
489
7fc8c9d5 490 if (!(val & MV88E6XXX_G2_EEPROM_CMD_WRITE_EN))
ec561276
VD
491 return -EROFS;
492
493 eeprom->len = 0;
494
495 if (offset & 1) {
496 err = mv88e6xxx_g2_eeprom_read16(chip, offset >> 1, &val);
497 if (err)
498 return err;
499
500 val = (*data++ << 8) | (val & 0xff);
501
502 err = mv88e6xxx_g2_eeprom_write16(chip, offset >> 1, val);
503 if (err)
504 return err;
505
506 offset++;
507 len--;
508 eeprom->len++;
509 }
510
511 while (len >= 2) {
512 val = *data++;
513 val |= *data++ << 8;
514
515 err = mv88e6xxx_g2_eeprom_write16(chip, offset >> 1, val);
516 if (err)
517 return err;
518
519 offset += 2;
520 len -= 2;
521 eeprom->len += 2;
522 }
523
524 if (len) {
525 err = mv88e6xxx_g2_eeprom_read16(chip, offset >> 1, &val);
526 if (err)
527 return err;
528
529 val = (val & 0xff00) | *data++;
530
531 err = mv88e6xxx_g2_eeprom_write16(chip, offset >> 1, val);
532 if (err)
533 return err;
534
535 offset++;
536 len--;
537 eeprom->len++;
538 }
539
540 return 0;
541}
542
543/* Offset 0x18: SMI PHY Command Register
544 * Offset 0x19: SMI PHY Data Register
545 */
546
547static int mv88e6xxx_g2_smi_phy_wait(struct mv88e6xxx_chip *chip)
548{
e289ef0d
VD
549 return mv88e6xxx_g2_wait(chip, MV88E6XXX_G2_SMI_PHY_CMD,
550 MV88E6XXX_G2_SMI_PHY_CMD_BUSY);
ec561276
VD
551}
552
553static int mv88e6xxx_g2_smi_phy_cmd(struct mv88e6xxx_chip *chip, u16 cmd)
554{
555 int err;
556
e289ef0d
VD
557 err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_SMI_PHY_CMD,
558 MV88E6XXX_G2_SMI_PHY_CMD_BUSY | cmd);
ec561276
VD
559 if (err)
560 return err;
561
562 return mv88e6xxx_g2_smi_phy_wait(chip);
563}
564
e289ef0d
VD
565static int mv88e6xxx_g2_smi_phy_access(struct mv88e6xxx_chip *chip,
566 bool external, bool c45, u16 op, int dev,
567 int reg)
cf3e80df 568{
e289ef0d 569 u16 cmd = op;
cf3e80df
AL
570
571 if (external)
e289ef0d
VD
572 cmd |= MV88E6390_G2_SMI_PHY_CMD_FUNC_EXTERNAL;
573 else
574 cmd |= MV88E6390_G2_SMI_PHY_CMD_FUNC_INTERNAL; /* empty mask */
cf3e80df 575
e289ef0d
VD
576 if (c45)
577 cmd |= MV88E6XXX_G2_SMI_PHY_CMD_MODE_45; /* empty mask */
578 else
579 cmd |= MV88E6XXX_G2_SMI_PHY_CMD_MODE_22;
cf3e80df 580
e289ef0d
VD
581 dev <<= __bf_shf(MV88E6XXX_G2_SMI_PHY_CMD_DEV_ADDR_MASK);
582 cmd |= dev & MV88E6XXX_G2_SMI_PHY_CMD_DEV_ADDR_MASK;
583 cmd |= reg & MV88E6XXX_G2_SMI_PHY_CMD_REG_ADDR_MASK;
cf3e80df
AL
584
585 return mv88e6xxx_g2_smi_phy_cmd(chip, cmd);
586}
587
e289ef0d
VD
588static int mv88e6xxx_g2_smi_phy_access_c22(struct mv88e6xxx_chip *chip,
589 bool external, u16 op, int dev,
590 int reg)
cf3e80df 591{
e289ef0d
VD
592 return mv88e6xxx_g2_smi_phy_access(chip, external, false, op, dev, reg);
593}
594
595/* IEEE 802.3 Clause 22 Read Data Register */
596static int mv88e6xxx_g2_smi_phy_read_data_c22(struct mv88e6xxx_chip *chip,
597 bool external, int dev, int reg,
598 u16 *data)
599{
600 u16 op = MV88E6XXX_G2_SMI_PHY_CMD_OP_22_READ_DATA;
cf3e80df 601 int err;
cf3e80df 602
e289ef0d 603 err = mv88e6xxx_g2_smi_phy_wait(chip);
cf3e80df
AL
604 if (err)
605 return err;
606
e289ef0d
VD
607 err = mv88e6xxx_g2_smi_phy_access_c22(chip, external, op, dev, reg);
608 if (err)
609 return err;
cf3e80df 610
e289ef0d
VD
611 return mv88e6xxx_g2_read(chip, MV88E6XXX_G2_SMI_PHY_DATA, data);
612}
cf3e80df 613
e289ef0d
VD
614/* IEEE 802.3 Clause 22 Write Data Register */
615static int mv88e6xxx_g2_smi_phy_write_data_c22(struct mv88e6xxx_chip *chip,
616 bool external, int dev, int reg,
617 u16 data)
618{
619 u16 op = MV88E6XXX_G2_SMI_PHY_CMD_OP_22_WRITE_DATA;
620 int err;
621
622 err = mv88e6xxx_g2_smi_phy_wait(chip);
cf3e80df
AL
623 if (err)
624 return err;
625
e289ef0d 626 err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_SMI_PHY_DATA, data);
cf3e80df
AL
627 if (err)
628 return err;
629
e289ef0d
VD
630 return mv88e6xxx_g2_smi_phy_access_c22(chip, external, op, dev, reg);
631}
cf3e80df 632
e289ef0d
VD
633static int mv88e6xxx_g2_smi_phy_access_c45(struct mv88e6xxx_chip *chip,
634 bool external, u16 op, int port,
635 int dev)
636{
637 return mv88e6xxx_g2_smi_phy_access(chip, external, true, op, port, dev);
cf3e80df
AL
638}
639
e289ef0d
VD
640/* IEEE 802.3 Clause 45 Write Address Register */
641static int mv88e6xxx_g2_smi_phy_write_addr_c45(struct mv88e6xxx_chip *chip,
642 bool external, int port, int dev,
643 int addr)
cf3e80df 644{
e289ef0d 645 u16 op = MV88E6XXX_G2_SMI_PHY_CMD_OP_45_WRITE_ADDR;
cf3e80df
AL
646 int err;
647
cf3e80df
AL
648 err = mv88e6xxx_g2_smi_phy_wait(chip);
649 if (err)
650 return err;
651
e289ef0d 652 err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_SMI_PHY_DATA, addr);
cf3e80df
AL
653 if (err)
654 return err;
655
e289ef0d 656 return mv88e6xxx_g2_smi_phy_access_c45(chip, external, op, port, dev);
cf3e80df
AL
657}
658
e289ef0d
VD
659/* IEEE 802.3 Clause 45 Read Data Register */
660static int mv88e6xxx_g2_smi_phy_read_data_c45(struct mv88e6xxx_chip *chip,
661 bool external, int port, int dev,
662 u16 *data)
ec561276 663{
e289ef0d
VD
664 u16 op = MV88E6XXX_G2_SMI_PHY_CMD_OP_45_READ_DATA;
665 int err;
cf3e80df 666
e289ef0d
VD
667 err = mv88e6xxx_g2_smi_phy_access_c45(chip, external, op, port, dev);
668 if (err)
669 return err;
670
671 return mv88e6xxx_g2_read(chip, MV88E6XXX_G2_SMI_PHY_DATA, data);
cf3e80df
AL
672}
673
e289ef0d
VD
674static int mv88e6xxx_g2_smi_phy_read_c45(struct mv88e6xxx_chip *chip,
675 bool external, int port, int reg,
676 u16 *data)
cf3e80df 677{
e289ef0d
VD
678 int dev = (reg >> 16) & 0x1f;
679 int addr = reg & 0xffff;
ec561276
VD
680 int err;
681
e289ef0d
VD
682 err = mv88e6xxx_g2_smi_phy_write_addr_c45(chip, external, port, dev,
683 addr);
cf3e80df
AL
684 if (err)
685 return err;
686
e289ef0d
VD
687 return mv88e6xxx_g2_smi_phy_read_data_c45(chip, external, port, dev,
688 data);
689}
c61a6a71 690
e289ef0d
VD
691/* IEEE 802.3 Clause 45 Write Data Register */
692static int mv88e6xxx_g2_smi_phy_write_data_c45(struct mv88e6xxx_chip *chip,
693 bool external, int port, int dev,
694 u16 data)
695{
696 u16 op = MV88E6XXX_G2_SMI_PHY_CMD_OP_45_WRITE_DATA;
697 int err;
ec561276 698
e289ef0d 699 err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_SMI_PHY_DATA, data);
ec561276
VD
700 if (err)
701 return err;
702
e289ef0d 703 return mv88e6xxx_g2_smi_phy_access_c45(chip, external, op, port, dev);
ec561276
VD
704}
705
e289ef0d
VD
706static int mv88e6xxx_g2_smi_phy_write_c45(struct mv88e6xxx_chip *chip,
707 bool external, int port, int reg,
708 u16 data)
ec561276 709{
e289ef0d
VD
710 int dev = (reg >> 16) & 0x1f;
711 int addr = reg & 0xffff;
ec561276
VD
712 int err;
713
e289ef0d
VD
714 err = mv88e6xxx_g2_smi_phy_write_addr_c45(chip, external, port, dev,
715 addr);
ec561276
VD
716 if (err)
717 return err;
718
e289ef0d
VD
719 return mv88e6xxx_g2_smi_phy_write_data_c45(chip, external, port, dev,
720 data);
721}
ec561276 722
e289ef0d
VD
723int mv88e6xxx_g2_smi_phy_read(struct mv88e6xxx_chip *chip, struct mii_bus *bus,
724 int addr, int reg, u16 *val)
725{
726 struct mv88e6xxx_mdio_bus *mdio_bus = bus->priv;
727 bool external = mdio_bus->external;
728
729 if (reg & MII_ADDR_C45)
730 return mv88e6xxx_g2_smi_phy_read_c45(chip, external, addr, reg,
731 val);
732
733 return mv88e6xxx_g2_smi_phy_read_data_c22(chip, external, addr, reg,
734 val);
ec561276
VD
735}
736
e289ef0d 737int mv88e6xxx_g2_smi_phy_write(struct mv88e6xxx_chip *chip, struct mii_bus *bus,
cf3e80df
AL
738 int addr, int reg, u16 val)
739{
740 struct mv88e6xxx_mdio_bus *mdio_bus = bus->priv;
741 bool external = mdio_bus->external;
742
743 if (reg & MII_ADDR_C45)
e289ef0d
VD
744 return mv88e6xxx_g2_smi_phy_write_c45(chip, external, addr, reg,
745 val);
cf3e80df 746
e289ef0d
VD
747 return mv88e6xxx_g2_smi_phy_write_data_c22(chip, external, addr, reg,
748 val);
cf3e80df
AL
749}
750
fcd25166
AL
751static int mv88e6097_watchdog_action(struct mv88e6xxx_chip *chip, int irq)
752{
753 u16 reg;
754
755 mv88e6xxx_g2_read(chip, GLOBAL2_WDOG_CONTROL, &reg);
756
757 dev_info(chip->dev, "Watchdog event: 0x%04x", reg);
758
759 return IRQ_HANDLED;
760}
761
762static void mv88e6097_watchdog_free(struct mv88e6xxx_chip *chip)
763{
764 u16 reg;
765
766 mv88e6xxx_g2_read(chip, GLOBAL2_WDOG_CONTROL, &reg);
767
768 reg &= ~(GLOBAL2_WDOG_CONTROL_EGRESS_ENABLE |
769 GLOBAL2_WDOG_CONTROL_QC_ENABLE);
770
771 mv88e6xxx_g2_write(chip, GLOBAL2_WDOG_CONTROL, reg);
772}
773
774static int mv88e6097_watchdog_setup(struct mv88e6xxx_chip *chip)
775{
776 return mv88e6xxx_g2_write(chip, GLOBAL2_WDOG_CONTROL,
777 GLOBAL2_WDOG_CONTROL_EGRESS_ENABLE |
778 GLOBAL2_WDOG_CONTROL_QC_ENABLE |
779 GLOBAL2_WDOG_CONTROL_SWRESET);
780}
781
782const struct mv88e6xxx_irq_ops mv88e6097_watchdog_ops = {
783 .irq_action = mv88e6097_watchdog_action,
784 .irq_setup = mv88e6097_watchdog_setup,
785 .irq_free = mv88e6097_watchdog_free,
786};
787
61303736
AL
788static int mv88e6390_watchdog_setup(struct mv88e6xxx_chip *chip)
789{
790 return mv88e6xxx_g2_update(chip, GLOBAL2_WDOG_CONTROL,
791 GLOBAL2_WDOG_INT_ENABLE |
792 GLOBAL2_WDOG_CUT_THROUGH |
793 GLOBAL2_WDOG_QUEUE_CONTROLLER |
794 GLOBAL2_WDOG_EGRESS |
795 GLOBAL2_WDOG_FORCE_IRQ);
796}
797
798static int mv88e6390_watchdog_action(struct mv88e6xxx_chip *chip, int irq)
799{
800 int err;
801 u16 reg;
802
803 mv88e6xxx_g2_write(chip, GLOBAL2_WDOG_CONTROL, GLOBAL2_WDOG_EVENT);
804 err = mv88e6xxx_g2_read(chip, GLOBAL2_WDOG_CONTROL, &reg);
805
806 dev_info(chip->dev, "Watchdog event: 0x%04x",
807 reg & GLOBAL2_WDOG_DATA_MASK);
808
809 mv88e6xxx_g2_write(chip, GLOBAL2_WDOG_CONTROL, GLOBAL2_WDOG_HISTORY);
810 err = mv88e6xxx_g2_read(chip, GLOBAL2_WDOG_CONTROL, &reg);
811
812 dev_info(chip->dev, "Watchdog history: 0x%04x",
813 reg & GLOBAL2_WDOG_DATA_MASK);
814
815 /* Trigger a software reset to try to recover the switch */
816 if (chip->info->ops->reset)
817 chip->info->ops->reset(chip);
818
819 mv88e6390_watchdog_setup(chip);
820
821 return IRQ_HANDLED;
822}
823
824static void mv88e6390_watchdog_free(struct mv88e6xxx_chip *chip)
825{
826 mv88e6xxx_g2_update(chip, GLOBAL2_WDOG_CONTROL,
827 GLOBAL2_WDOG_INT_ENABLE);
828}
829
830const struct mv88e6xxx_irq_ops mv88e6390_watchdog_ops = {
831 .irq_action = mv88e6390_watchdog_action,
832 .irq_setup = mv88e6390_watchdog_setup,
833 .irq_free = mv88e6390_watchdog_free,
834};
835
fcd25166
AL
836static irqreturn_t mv88e6xxx_g2_watchdog_thread_fn(int irq, void *dev_id)
837{
838 struct mv88e6xxx_chip *chip = dev_id;
839 irqreturn_t ret = IRQ_NONE;
840
841 mutex_lock(&chip->reg_lock);
842 if (chip->info->ops->watchdog_ops->irq_action)
843 ret = chip->info->ops->watchdog_ops->irq_action(chip, irq);
844 mutex_unlock(&chip->reg_lock);
845
846 return ret;
847}
848
849static void mv88e6xxx_g2_watchdog_free(struct mv88e6xxx_chip *chip)
850{
851 mutex_lock(&chip->reg_lock);
852 if (chip->info->ops->watchdog_ops->irq_free)
853 chip->info->ops->watchdog_ops->irq_free(chip);
854 mutex_unlock(&chip->reg_lock);
855
856 free_irq(chip->watchdog_irq, chip);
857 irq_dispose_mapping(chip->watchdog_irq);
858}
859
860static int mv88e6xxx_g2_watchdog_setup(struct mv88e6xxx_chip *chip)
861{
862 int err;
863
864 chip->watchdog_irq = irq_find_mapping(chip->g2_irq.domain,
865 GLOBAL2_INT_SOURCE_WATCHDOG);
866 if (chip->watchdog_irq < 0)
867 return chip->watchdog_irq;
868
869 err = request_threaded_irq(chip->watchdog_irq, NULL,
870 mv88e6xxx_g2_watchdog_thread_fn,
871 IRQF_ONESHOT | IRQF_TRIGGER_FALLING,
872 "mv88e6xxx-watchdog", chip);
873 if (err)
874 return err;
875
876 mutex_lock(&chip->reg_lock);
877 if (chip->info->ops->watchdog_ops->irq_setup)
878 err = chip->info->ops->watchdog_ops->irq_setup(chip);
879 mutex_unlock(&chip->reg_lock);
880
881 return err;
882}
883
81228996
VD
884/* Offset 0x1D: Misc Register */
885
886static int mv88e6xxx_g2_misc_5_bit_port(struct mv88e6xxx_chip *chip,
887 bool port_5_bit)
888{
889 u16 val;
890 int err;
891
892 err = mv88e6xxx_g2_read(chip, GLOBAL2_MISC, &val);
893 if (err)
894 return err;
895
896 if (port_5_bit)
897 val |= GLOBAL2_MISC_5_BIT_PORT;
898 else
899 val &= ~GLOBAL2_MISC_5_BIT_PORT;
900
901 return mv88e6xxx_g2_write(chip, GLOBAL2_MISC, val);
902}
903
904int mv88e6xxx_g2_misc_4_bit_port(struct mv88e6xxx_chip *chip)
905{
906 return mv88e6xxx_g2_misc_5_bit_port(chip, false);
907}
908
dc30c35b
AL
909static void mv88e6xxx_g2_irq_mask(struct irq_data *d)
910{
911 struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
912 unsigned int n = d->hwirq;
913
914 chip->g2_irq.masked |= (1 << n);
915}
916
917static void mv88e6xxx_g2_irq_unmask(struct irq_data *d)
918{
919 struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
920 unsigned int n = d->hwirq;
921
922 chip->g2_irq.masked &= ~(1 << n);
923}
924
925static irqreturn_t mv88e6xxx_g2_irq_thread_fn(int irq, void *dev_id)
926{
927 struct mv88e6xxx_chip *chip = dev_id;
928 unsigned int nhandled = 0;
929 unsigned int sub_irq;
930 unsigned int n;
931 int err;
932 u16 reg;
933
934 mutex_lock(&chip->reg_lock);
935 err = mv88e6xxx_g2_read(chip, GLOBAL2_INT_SOURCE, &reg);
936 mutex_unlock(&chip->reg_lock);
937 if (err)
938 goto out;
939
940 for (n = 0; n < 16; ++n) {
941 if (reg & (1 << n)) {
942 sub_irq = irq_find_mapping(chip->g2_irq.domain, n);
943 handle_nested_irq(sub_irq);
944 ++nhandled;
945 }
946 }
947out:
948 return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE);
949}
950
951static void mv88e6xxx_g2_irq_bus_lock(struct irq_data *d)
952{
953 struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
954
955 mutex_lock(&chip->reg_lock);
956}
957
958static void mv88e6xxx_g2_irq_bus_sync_unlock(struct irq_data *d)
959{
960 struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
961
962 mv88e6xxx_g2_write(chip, GLOBAL2_INT_MASK, ~chip->g2_irq.masked);
963
964 mutex_unlock(&chip->reg_lock);
965}
966
967static struct irq_chip mv88e6xxx_g2_irq_chip = {
968 .name = "mv88e6xxx-g2",
969 .irq_mask = mv88e6xxx_g2_irq_mask,
970 .irq_unmask = mv88e6xxx_g2_irq_unmask,
971 .irq_bus_lock = mv88e6xxx_g2_irq_bus_lock,
972 .irq_bus_sync_unlock = mv88e6xxx_g2_irq_bus_sync_unlock,
973};
974
975static int mv88e6xxx_g2_irq_domain_map(struct irq_domain *d,
976 unsigned int irq,
977 irq_hw_number_t hwirq)
978{
979 struct mv88e6xxx_chip *chip = d->host_data;
980
981 irq_set_chip_data(irq, d->host_data);
982 irq_set_chip_and_handler(irq, &chip->g2_irq.chip, handle_level_irq);
983 irq_set_noprobe(irq);
984
985 return 0;
986}
987
988static const struct irq_domain_ops mv88e6xxx_g2_irq_domain_ops = {
989 .map = mv88e6xxx_g2_irq_domain_map,
990 .xlate = irq_domain_xlate_twocell,
991};
992
993void mv88e6xxx_g2_irq_free(struct mv88e6xxx_chip *chip)
994{
995 int irq, virq;
996
fcd25166
AL
997 mv88e6xxx_g2_watchdog_free(chip);
998
8e757eba
AL
999 free_irq(chip->device_irq, chip);
1000 irq_dispose_mapping(chip->device_irq);
1001
dc30c35b
AL
1002 for (irq = 0; irq < 16; irq++) {
1003 virq = irq_find_mapping(chip->g2_irq.domain, irq);
1004 irq_dispose_mapping(virq);
1005 }
1006
1007 irq_domain_remove(chip->g2_irq.domain);
1008}
1009
1010int mv88e6xxx_g2_irq_setup(struct mv88e6xxx_chip *chip)
1011{
8e757eba 1012 int err, irq, virq;
dc30c35b
AL
1013
1014 if (!chip->dev->of_node)
1015 return -EINVAL;
1016
1017 chip->g2_irq.domain = irq_domain_add_simple(
1018 chip->dev->of_node, 16, 0, &mv88e6xxx_g2_irq_domain_ops, chip);
1019 if (!chip->g2_irq.domain)
1020 return -ENOMEM;
1021
1022 for (irq = 0; irq < 16; irq++)
1023 irq_create_mapping(chip->g2_irq.domain, irq);
1024
1025 chip->g2_irq.chip = mv88e6xxx_g2_irq_chip;
1026 chip->g2_irq.masked = ~0;
1027
8e757eba 1028 chip->device_irq = irq_find_mapping(chip->g1_irq.domain,
82466921 1029 MV88E6XXX_G1_STS_IRQ_DEVICE);
8e757eba
AL
1030 if (chip->device_irq < 0) {
1031 err = chip->device_irq;
dc30c35b
AL
1032 goto out;
1033 }
1034
8e757eba
AL
1035 err = request_threaded_irq(chip->device_irq, NULL,
1036 mv88e6xxx_g2_irq_thread_fn,
1037 IRQF_ONESHOT, "mv88e6xxx-g1", chip);
dc30c35b
AL
1038 if (err)
1039 goto out;
1040
fcd25166 1041 return mv88e6xxx_g2_watchdog_setup(chip);
8e757eba 1042
dc30c35b 1043out:
8e757eba
AL
1044 for (irq = 0; irq < 16; irq++) {
1045 virq = irq_find_mapping(chip->g2_irq.domain, irq);
1046 irq_dispose_mapping(virq);
1047 }
1048
1049 irq_domain_remove(chip->g2_irq.domain);
dc30c35b
AL
1050
1051 return err;
1052}
1053
ec561276
VD
1054int mv88e6xxx_g2_setup(struct mv88e6xxx_chip *chip)
1055{
1056 u16 reg;
1057 int err;
1058
ec561276
VD
1059 /* Ignore removed tag data on doubly tagged packets, disable
1060 * flow control messages, force flow control priority to the
1061 * highest, and send all special multicast frames to the CPU
1062 * port at the highest priority.
1063 */
6bff47be 1064 reg = MV88E6XXX_G2_SWITCH_MGMT_FORCE_FLOW_CTL_PRI | (0x7 << 4);
ec561276
VD
1065 if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_0X) ||
1066 mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_2X))
6bff47be
VD
1067 reg |= MV88E6XXX_G2_SWITCH_MGMT_RSVD2CPU | 0x7;
1068 err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_SWITCH_MGMT, reg);
ec561276
VD
1069 if (err)
1070 return err;
1071
1072 /* Program the DSA routing table. */
1073 err = mv88e6xxx_g2_set_device_mapping(chip);
1074 if (err)
1075 return err;
1076
1077 /* Clear all trunk masks and mapping. */
1078 err = mv88e6xxx_g2_clear_trunk(chip);
1079 if (err)
1080 return err;
1081
ec561276
VD
1082 if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_POT)) {
1083 /* Clear the priority override table. */
1084 err = mv88e6xxx_g2_clear_pot(chip);
1085 if (err)
1086 return err;
1087 }
1088
1089 return 0;
1090}
This page took 0.280168 seconds and 4 git commands to generate.