net: dsa: mv88e6xxx: Fix cleanup on error for g1 interrupt setup
[linux-2.6-block.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 *
7 * Copyright (c) 2016 Vivien Didelot <vivien.didelot@savoirfairelinux.com>
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
dc30c35b 15#include <linux/irqdomain.h>
ec561276
VD
16#include "mv88e6xxx.h"
17#include "global2.h"
18
9fe850fb
VD
19#define ADDR_GLOBAL2 0x1c
20
21static int mv88e6xxx_g2_read(struct mv88e6xxx_chip *chip, int reg, u16 *val)
22{
23 return mv88e6xxx_read(chip, ADDR_GLOBAL2, reg, val);
24}
25
26static int mv88e6xxx_g2_write(struct mv88e6xxx_chip *chip, int reg, u16 val)
27{
28 return mv88e6xxx_write(chip, ADDR_GLOBAL2, reg, val);
29}
30
31static int mv88e6xxx_g2_update(struct mv88e6xxx_chip *chip, int reg, u16 update)
32{
33 return mv88e6xxx_update(chip, ADDR_GLOBAL2, reg, update);
34}
35
36static int mv88e6xxx_g2_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask)
37{
38 return mv88e6xxx_wait(chip, ADDR_GLOBAL2, reg, mask);
39}
40
ec561276
VD
41/* Offset 0x06: Device Mapping Table register */
42
43static int mv88e6xxx_g2_device_mapping_write(struct mv88e6xxx_chip *chip,
44 int target, int port)
45{
46 u16 val = (target << 8) | (port & 0xf);
47
9fe850fb 48 return mv88e6xxx_g2_update(chip, GLOBAL2_DEVICE_MAPPING, val);
ec561276
VD
49}
50
51static int mv88e6xxx_g2_set_device_mapping(struct mv88e6xxx_chip *chip)
52{
53 int target, port;
54 int err;
55
56 /* Initialize the routing port to the 32 possible target devices */
57 for (target = 0; target < 32; ++target) {
58 port = 0xf;
59
60 if (target < DSA_MAX_SWITCHES) {
61 port = chip->ds->rtable[target];
62 if (port == DSA_RTABLE_NONE)
63 port = 0xf;
64 }
65
66 err = mv88e6xxx_g2_device_mapping_write(chip, target, port);
67 if (err)
68 break;
69 }
70
71 return err;
72}
73
74/* Offset 0x07: Trunk Mask Table register */
75
76static int mv88e6xxx_g2_trunk_mask_write(struct mv88e6xxx_chip *chip, int num,
77 bool hask, u16 mask)
78{
370b4ffb 79 const u16 port_mask = BIT(mv88e6xxx_num_ports(chip)) - 1;
ec561276
VD
80 u16 val = (num << 12) | (mask & port_mask);
81
82 if (hask)
83 val |= GLOBAL2_TRUNK_MASK_HASK;
84
9fe850fb 85 return mv88e6xxx_g2_update(chip, GLOBAL2_TRUNK_MASK, val);
ec561276
VD
86}
87
88/* Offset 0x08: Trunk Mapping Table register */
89
90static int mv88e6xxx_g2_trunk_mapping_write(struct mv88e6xxx_chip *chip, int id,
91 u16 map)
92{
370b4ffb 93 const u16 port_mask = BIT(mv88e6xxx_num_ports(chip)) - 1;
ec561276
VD
94 u16 val = (id << 11) | (map & port_mask);
95
9fe850fb 96 return mv88e6xxx_g2_update(chip, GLOBAL2_TRUNK_MAPPING, val);
ec561276
VD
97}
98
99static int mv88e6xxx_g2_clear_trunk(struct mv88e6xxx_chip *chip)
100{
370b4ffb 101 const u16 port_mask = BIT(mv88e6xxx_num_ports(chip)) - 1;
ec561276
VD
102 int i, err;
103
104 /* Clear all eight possible Trunk Mask vectors */
105 for (i = 0; i < 8; ++i) {
106 err = mv88e6xxx_g2_trunk_mask_write(chip, i, false, port_mask);
107 if (err)
108 return err;
109 }
110
111 /* Clear all sixteen possible Trunk ID routing vectors */
112 for (i = 0; i < 16; ++i) {
113 err = mv88e6xxx_g2_trunk_mapping_write(chip, i, 0);
114 if (err)
115 return err;
116 }
117
118 return 0;
119}
120
121/* Offset 0x09: Ingress Rate Command register
122 * Offset 0x0A: Ingress Rate Data register
123 */
124
125static int mv88e6xxx_g2_clear_irl(struct mv88e6xxx_chip *chip)
126{
127 int port, err;
128
129 /* Init all Ingress Rate Limit resources of all ports */
370b4ffb 130 for (port = 0; port < mv88e6xxx_num_ports(chip); ++port) {
ec561276 131 /* XXX newer chips (like 88E6390) have different 2-bit ops */
9fe850fb
VD
132 err = mv88e6xxx_g2_write(chip, GLOBAL2_IRL_CMD,
133 GLOBAL2_IRL_CMD_OP_INIT_ALL |
134 (port << 8));
ec561276
VD
135 if (err)
136 break;
137
138 /* Wait for the operation to complete */
9fe850fb
VD
139 err = mv88e6xxx_g2_wait(chip, GLOBAL2_IRL_CMD,
140 GLOBAL2_IRL_CMD_BUSY);
ec561276
VD
141 if (err)
142 break;
143 }
144
145 return err;
146}
147
148/* Offset 0x0D: Switch MAC/WoL/WoF register */
149
150static int mv88e6xxx_g2_switch_mac_write(struct mv88e6xxx_chip *chip,
151 unsigned int pointer, u8 data)
152{
153 u16 val = (pointer << 8) | data;
154
9fe850fb 155 return mv88e6xxx_g2_update(chip, GLOBAL2_SWITCH_MAC, val);
ec561276
VD
156}
157
158int mv88e6xxx_g2_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr)
159{
160 int i, err;
161
162 for (i = 0; i < 6; i++) {
163 err = mv88e6xxx_g2_switch_mac_write(chip, i, addr[i]);
164 if (err)
165 break;
166 }
167
168 return err;
169}
170
171/* Offset 0x0F: Priority Override Table */
172
173static int mv88e6xxx_g2_pot_write(struct mv88e6xxx_chip *chip, int pointer,
174 u8 data)
175{
176 u16 val = (pointer << 8) | (data & 0x7);
177
9fe850fb 178 return mv88e6xxx_g2_update(chip, GLOBAL2_PRIO_OVERRIDE, val);
ec561276
VD
179}
180
181static int mv88e6xxx_g2_clear_pot(struct mv88e6xxx_chip *chip)
182{
183 int i, err;
184
185 /* Clear all sixteen possible Priority Override entries */
186 for (i = 0; i < 16; i++) {
187 err = mv88e6xxx_g2_pot_write(chip, i, 0);
188 if (err)
189 break;
190 }
191
192 return err;
193}
194
195/* Offset 0x14: EEPROM Command
196 * Offset 0x15: EEPROM Data
197 */
198
199static int mv88e6xxx_g2_eeprom_wait(struct mv88e6xxx_chip *chip)
200{
9fe850fb
VD
201 return mv88e6xxx_g2_wait(chip, GLOBAL2_EEPROM_CMD,
202 GLOBAL2_EEPROM_CMD_BUSY |
203 GLOBAL2_EEPROM_CMD_RUNNING);
ec561276
VD
204}
205
206static int mv88e6xxx_g2_eeprom_cmd(struct mv88e6xxx_chip *chip, u16 cmd)
207{
208 int err;
209
9fe850fb 210 err = mv88e6xxx_g2_write(chip, GLOBAL2_EEPROM_CMD, cmd);
ec561276
VD
211 if (err)
212 return err;
213
214 return mv88e6xxx_g2_eeprom_wait(chip);
215}
216
217static int mv88e6xxx_g2_eeprom_read16(struct mv88e6xxx_chip *chip,
218 u8 addr, u16 *data)
219{
220 u16 cmd = GLOBAL2_EEPROM_CMD_OP_READ | addr;
221 int err;
222
223 err = mv88e6xxx_g2_eeprom_wait(chip);
224 if (err)
225 return err;
226
227 err = mv88e6xxx_g2_eeprom_cmd(chip, cmd);
228 if (err)
229 return err;
230
9fe850fb 231 return mv88e6xxx_g2_read(chip, GLOBAL2_EEPROM_DATA, data);
ec561276
VD
232}
233
234static int mv88e6xxx_g2_eeprom_write16(struct mv88e6xxx_chip *chip,
235 u8 addr, u16 data)
236{
237 u16 cmd = GLOBAL2_EEPROM_CMD_OP_WRITE | addr;
238 int err;
239
240 err = mv88e6xxx_g2_eeprom_wait(chip);
241 if (err)
242 return err;
243
9fe850fb 244 err = mv88e6xxx_g2_write(chip, GLOBAL2_EEPROM_DATA, data);
ec561276
VD
245 if (err)
246 return err;
247
248 return mv88e6xxx_g2_eeprom_cmd(chip, cmd);
249}
250
251int mv88e6xxx_g2_get_eeprom16(struct mv88e6xxx_chip *chip,
252 struct ethtool_eeprom *eeprom, u8 *data)
253{
254 unsigned int offset = eeprom->offset;
255 unsigned int len = eeprom->len;
256 u16 val;
257 int err;
258
259 eeprom->len = 0;
260
261 if (offset & 1) {
262 err = mv88e6xxx_g2_eeprom_read16(chip, offset >> 1, &val);
263 if (err)
264 return err;
265
266 *data++ = (val >> 8) & 0xff;
267
268 offset++;
269 len--;
270 eeprom->len++;
271 }
272
273 while (len >= 2) {
274 err = mv88e6xxx_g2_eeprom_read16(chip, offset >> 1, &val);
275 if (err)
276 return err;
277
278 *data++ = val & 0xff;
279 *data++ = (val >> 8) & 0xff;
280
281 offset += 2;
282 len -= 2;
283 eeprom->len += 2;
284 }
285
286 if (len) {
287 err = mv88e6xxx_g2_eeprom_read16(chip, offset >> 1, &val);
288 if (err)
289 return err;
290
291 *data++ = val & 0xff;
292
293 offset++;
294 len--;
295 eeprom->len++;
296 }
297
298 return 0;
299}
300
301int mv88e6xxx_g2_set_eeprom16(struct mv88e6xxx_chip *chip,
302 struct ethtool_eeprom *eeprom, u8 *data)
303{
304 unsigned int offset = eeprom->offset;
305 unsigned int len = eeprom->len;
306 u16 val;
307 int err;
308
309 /* Ensure the RO WriteEn bit is set */
9fe850fb 310 err = mv88e6xxx_g2_read(chip, GLOBAL2_EEPROM_CMD, &val);
ec561276
VD
311 if (err)
312 return err;
313
314 if (!(val & GLOBAL2_EEPROM_CMD_WRITE_EN))
315 return -EROFS;
316
317 eeprom->len = 0;
318
319 if (offset & 1) {
320 err = mv88e6xxx_g2_eeprom_read16(chip, offset >> 1, &val);
321 if (err)
322 return err;
323
324 val = (*data++ << 8) | (val & 0xff);
325
326 err = mv88e6xxx_g2_eeprom_write16(chip, offset >> 1, val);
327 if (err)
328 return err;
329
330 offset++;
331 len--;
332 eeprom->len++;
333 }
334
335 while (len >= 2) {
336 val = *data++;
337 val |= *data++ << 8;
338
339 err = mv88e6xxx_g2_eeprom_write16(chip, offset >> 1, val);
340 if (err)
341 return err;
342
343 offset += 2;
344 len -= 2;
345 eeprom->len += 2;
346 }
347
348 if (len) {
349 err = mv88e6xxx_g2_eeprom_read16(chip, offset >> 1, &val);
350 if (err)
351 return err;
352
353 val = (val & 0xff00) | *data++;
354
355 err = mv88e6xxx_g2_eeprom_write16(chip, offset >> 1, val);
356 if (err)
357 return err;
358
359 offset++;
360 len--;
361 eeprom->len++;
362 }
363
364 return 0;
365}
366
367/* Offset 0x18: SMI PHY Command Register
368 * Offset 0x19: SMI PHY Data Register
369 */
370
371static int mv88e6xxx_g2_smi_phy_wait(struct mv88e6xxx_chip *chip)
372{
9fe850fb
VD
373 return mv88e6xxx_g2_wait(chip, GLOBAL2_SMI_PHY_CMD,
374 GLOBAL2_SMI_PHY_CMD_BUSY);
ec561276
VD
375}
376
377static int mv88e6xxx_g2_smi_phy_cmd(struct mv88e6xxx_chip *chip, u16 cmd)
378{
379 int err;
380
9fe850fb 381 err = mv88e6xxx_g2_write(chip, GLOBAL2_SMI_PHY_CMD, cmd);
ec561276
VD
382 if (err)
383 return err;
384
385 return mv88e6xxx_g2_smi_phy_wait(chip);
386}
387
388int mv88e6xxx_g2_smi_phy_read(struct mv88e6xxx_chip *chip, int addr, int reg,
389 u16 *val)
390{
391 u16 cmd = GLOBAL2_SMI_PHY_CMD_OP_22_READ_DATA | (addr << 5) | reg;
392 int err;
393
394 err = mv88e6xxx_g2_smi_phy_wait(chip);
395 if (err)
396 return err;
397
398 err = mv88e6xxx_g2_smi_phy_cmd(chip, cmd);
399 if (err)
400 return err;
401
9fe850fb 402 return mv88e6xxx_g2_read(chip, GLOBAL2_SMI_PHY_DATA, val);
ec561276
VD
403}
404
405int mv88e6xxx_g2_smi_phy_write(struct mv88e6xxx_chip *chip, int addr, int reg,
406 u16 val)
407{
408 u16 cmd = GLOBAL2_SMI_PHY_CMD_OP_22_WRITE_DATA | (addr << 5) | reg;
409 int err;
410
411 err = mv88e6xxx_g2_smi_phy_wait(chip);
412 if (err)
413 return err;
414
9fe850fb 415 err = mv88e6xxx_g2_write(chip, GLOBAL2_SMI_PHY_DATA, val);
ec561276
VD
416 if (err)
417 return err;
418
419 return mv88e6xxx_g2_smi_phy_cmd(chip, cmd);
420}
421
dc30c35b
AL
422static void mv88e6xxx_g2_irq_mask(struct irq_data *d)
423{
424 struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
425 unsigned int n = d->hwirq;
426
427 chip->g2_irq.masked |= (1 << n);
428}
429
430static void mv88e6xxx_g2_irq_unmask(struct irq_data *d)
431{
432 struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
433 unsigned int n = d->hwirq;
434
435 chip->g2_irq.masked &= ~(1 << n);
436}
437
438static irqreturn_t mv88e6xxx_g2_irq_thread_fn(int irq, void *dev_id)
439{
440 struct mv88e6xxx_chip *chip = dev_id;
441 unsigned int nhandled = 0;
442 unsigned int sub_irq;
443 unsigned int n;
444 int err;
445 u16 reg;
446
447 mutex_lock(&chip->reg_lock);
448 err = mv88e6xxx_g2_read(chip, GLOBAL2_INT_SOURCE, &reg);
449 mutex_unlock(&chip->reg_lock);
450 if (err)
451 goto out;
452
453 for (n = 0; n < 16; ++n) {
454 if (reg & (1 << n)) {
455 sub_irq = irq_find_mapping(chip->g2_irq.domain, n);
456 handle_nested_irq(sub_irq);
457 ++nhandled;
458 }
459 }
460out:
461 return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE);
462}
463
464static void mv88e6xxx_g2_irq_bus_lock(struct irq_data *d)
465{
466 struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
467
468 mutex_lock(&chip->reg_lock);
469}
470
471static void mv88e6xxx_g2_irq_bus_sync_unlock(struct irq_data *d)
472{
473 struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
474
475 mv88e6xxx_g2_write(chip, GLOBAL2_INT_MASK, ~chip->g2_irq.masked);
476
477 mutex_unlock(&chip->reg_lock);
478}
479
480static struct irq_chip mv88e6xxx_g2_irq_chip = {
481 .name = "mv88e6xxx-g2",
482 .irq_mask = mv88e6xxx_g2_irq_mask,
483 .irq_unmask = mv88e6xxx_g2_irq_unmask,
484 .irq_bus_lock = mv88e6xxx_g2_irq_bus_lock,
485 .irq_bus_sync_unlock = mv88e6xxx_g2_irq_bus_sync_unlock,
486};
487
488static int mv88e6xxx_g2_irq_domain_map(struct irq_domain *d,
489 unsigned int irq,
490 irq_hw_number_t hwirq)
491{
492 struct mv88e6xxx_chip *chip = d->host_data;
493
494 irq_set_chip_data(irq, d->host_data);
495 irq_set_chip_and_handler(irq, &chip->g2_irq.chip, handle_level_irq);
496 irq_set_noprobe(irq);
497
498 return 0;
499}
500
501static const struct irq_domain_ops mv88e6xxx_g2_irq_domain_ops = {
502 .map = mv88e6xxx_g2_irq_domain_map,
503 .xlate = irq_domain_xlate_twocell,
504};
505
506void mv88e6xxx_g2_irq_free(struct mv88e6xxx_chip *chip)
507{
508 int irq, virq;
509
510 for (irq = 0; irq < 16; irq++) {
511 virq = irq_find_mapping(chip->g2_irq.domain, irq);
512 irq_dispose_mapping(virq);
513 }
514
515 irq_domain_remove(chip->g2_irq.domain);
516}
517
518int mv88e6xxx_g2_irq_setup(struct mv88e6xxx_chip *chip)
519{
520 int device_irq;
521 int err, irq;
522
523 if (!chip->dev->of_node)
524 return -EINVAL;
525
526 chip->g2_irq.domain = irq_domain_add_simple(
527 chip->dev->of_node, 16, 0, &mv88e6xxx_g2_irq_domain_ops, chip);
528 if (!chip->g2_irq.domain)
529 return -ENOMEM;
530
531 for (irq = 0; irq < 16; irq++)
532 irq_create_mapping(chip->g2_irq.domain, irq);
533
534 chip->g2_irq.chip = mv88e6xxx_g2_irq_chip;
535 chip->g2_irq.masked = ~0;
536
537 device_irq = irq_find_mapping(chip->g1_irq.domain,
538 GLOBAL_STATUS_IRQ_DEVICE);
539 if (device_irq < 0) {
540 err = device_irq;
541 goto out;
542 }
543
544 err = devm_request_threaded_irq(chip->dev, device_irq, NULL,
545 mv88e6xxx_g2_irq_thread_fn,
546 IRQF_ONESHOT, "mv88e6xxx-g1", chip);
547 if (err)
548 goto out;
549
550 return 0;
551out:
552 mv88e6xxx_g2_irq_free(chip);
553
554 return err;
555}
556
ec561276
VD
557int mv88e6xxx_g2_setup(struct mv88e6xxx_chip *chip)
558{
559 u16 reg;
560 int err;
561
562 if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_2X)) {
563 /* Consider the frames with reserved multicast destination
564 * addresses matching 01:80:c2:00:00:2x as MGMT.
565 */
9fe850fb 566 err = mv88e6xxx_g2_write(chip, GLOBAL2_MGMT_EN_2X, 0xffff);
ec561276
VD
567 if (err)
568 return err;
569 }
570
571 if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_0X)) {
572 /* Consider the frames with reserved multicast destination
573 * addresses matching 01:80:c2:00:00:0x as MGMT.
574 */
9fe850fb 575 err = mv88e6xxx_g2_write(chip, GLOBAL2_MGMT_EN_0X, 0xffff);
ec561276
VD
576 if (err)
577 return err;
578 }
579
580 /* Ignore removed tag data on doubly tagged packets, disable
581 * flow control messages, force flow control priority to the
582 * highest, and send all special multicast frames to the CPU
583 * port at the highest priority.
584 */
585 reg = GLOBAL2_SWITCH_MGMT_FORCE_FLOW_CTRL_PRI | (0x7 << 4);
586 if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_0X) ||
587 mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_2X))
588 reg |= GLOBAL2_SWITCH_MGMT_RSVD2CPU | 0x7;
9fe850fb 589 err = mv88e6xxx_g2_write(chip, GLOBAL2_SWITCH_MGMT, reg);
ec561276
VD
590 if (err)
591 return err;
592
593 /* Program the DSA routing table. */
594 err = mv88e6xxx_g2_set_device_mapping(chip);
595 if (err)
596 return err;
597
598 /* Clear all trunk masks and mapping. */
599 err = mv88e6xxx_g2_clear_trunk(chip);
600 if (err)
601 return err;
602
603 if (mv88e6xxx_has(chip, MV88E6XXX_FLAGS_IRL)) {
604 /* Disable ingress rate limiting by resetting all per port
605 * ingress rate limit resources to their initial state.
606 */
607 err = mv88e6xxx_g2_clear_irl(chip);
608 if (err)
609 return err;
610 }
611
612 if (mv88e6xxx_has(chip, MV88E6XXX_FLAGS_PVT)) {
613 /* Initialize Cross-chip Port VLAN Table to reset defaults */
9fe850fb
VD
614 err = mv88e6xxx_g2_write(chip, GLOBAL2_PVT_ADDR,
615 GLOBAL2_PVT_ADDR_OP_INIT_ONES);
ec561276
VD
616 if (err)
617 return err;
618 }
619
620 if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_POT)) {
621 /* Clear the priority override table. */
622 err = mv88e6xxx_g2_clear_pot(chip);
623 if (err)
624 return err;
625 }
626
627 return 0;
628}