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