2 * Marvell 88E6xxx Switch Global 2 Registers support (device address 0x1C)
4 * Copyright (c) 2008 Marvell Semiconductor
6 * Copyright (c) 2016 Vivien Didelot <vivien.didelot@savoirfairelinux.com>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
14 #include "mv88e6xxx.h"
17 #define ADDR_GLOBAL2 0x1c
19 static int mv88e6xxx_g2_read(struct mv88e6xxx_chip *chip, int reg, u16 *val)
21 return mv88e6xxx_read(chip, ADDR_GLOBAL2, reg, val);
24 static int mv88e6xxx_g2_write(struct mv88e6xxx_chip *chip, int reg, u16 val)
26 return mv88e6xxx_write(chip, ADDR_GLOBAL2, reg, val);
29 static int mv88e6xxx_g2_update(struct mv88e6xxx_chip *chip, int reg, u16 update)
31 return mv88e6xxx_update(chip, ADDR_GLOBAL2, reg, update);
34 static int mv88e6xxx_g2_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask)
36 return mv88e6xxx_wait(chip, ADDR_GLOBAL2, reg, mask);
39 /* Offset 0x06: Device Mapping Table register */
41 static int mv88e6xxx_g2_device_mapping_write(struct mv88e6xxx_chip *chip,
44 u16 val = (target << 8) | (port & 0xf);
46 return mv88e6xxx_g2_update(chip, GLOBAL2_DEVICE_MAPPING, val);
49 static int mv88e6xxx_g2_set_device_mapping(struct mv88e6xxx_chip *chip)
54 /* Initialize the routing port to the 32 possible target devices */
55 for (target = 0; target < 32; ++target) {
58 if (target < DSA_MAX_SWITCHES) {
59 port = chip->ds->rtable[target];
60 if (port == DSA_RTABLE_NONE)
64 err = mv88e6xxx_g2_device_mapping_write(chip, target, port);
72 /* Offset 0x07: Trunk Mask Table register */
74 static int mv88e6xxx_g2_trunk_mask_write(struct mv88e6xxx_chip *chip, int num,
77 const u16 port_mask = BIT(mv88e6xxx_num_ports(chip)) - 1;
78 u16 val = (num << 12) | (mask & port_mask);
81 val |= GLOBAL2_TRUNK_MASK_HASK;
83 return mv88e6xxx_g2_update(chip, GLOBAL2_TRUNK_MASK, val);
86 /* Offset 0x08: Trunk Mapping Table register */
88 static int mv88e6xxx_g2_trunk_mapping_write(struct mv88e6xxx_chip *chip, int id,
91 const u16 port_mask = BIT(mv88e6xxx_num_ports(chip)) - 1;
92 u16 val = (id << 11) | (map & port_mask);
94 return mv88e6xxx_g2_update(chip, GLOBAL2_TRUNK_MAPPING, val);
97 static int mv88e6xxx_g2_clear_trunk(struct mv88e6xxx_chip *chip)
99 const u16 port_mask = BIT(mv88e6xxx_num_ports(chip)) - 1;
102 /* Clear all eight possible Trunk Mask vectors */
103 for (i = 0; i < 8; ++i) {
104 err = mv88e6xxx_g2_trunk_mask_write(chip, i, false, port_mask);
109 /* Clear all sixteen possible Trunk ID routing vectors */
110 for (i = 0; i < 16; ++i) {
111 err = mv88e6xxx_g2_trunk_mapping_write(chip, i, 0);
119 /* Offset 0x09: Ingress Rate Command register
120 * Offset 0x0A: Ingress Rate Data register
123 static int mv88e6xxx_g2_clear_irl(struct mv88e6xxx_chip *chip)
127 /* Init all Ingress Rate Limit resources of all ports */
128 for (port = 0; port < mv88e6xxx_num_ports(chip); ++port) {
129 /* XXX newer chips (like 88E6390) have different 2-bit ops */
130 err = mv88e6xxx_g2_write(chip, GLOBAL2_IRL_CMD,
131 GLOBAL2_IRL_CMD_OP_INIT_ALL |
136 /* Wait for the operation to complete */
137 err = mv88e6xxx_g2_wait(chip, GLOBAL2_IRL_CMD,
138 GLOBAL2_IRL_CMD_BUSY);
146 /* Offset 0x0D: Switch MAC/WoL/WoF register */
148 static int mv88e6xxx_g2_switch_mac_write(struct mv88e6xxx_chip *chip,
149 unsigned int pointer, u8 data)
151 u16 val = (pointer << 8) | data;
153 return mv88e6xxx_g2_update(chip, GLOBAL2_SWITCH_MAC, val);
156 int mv88e6xxx_g2_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr)
160 for (i = 0; i < 6; i++) {
161 err = mv88e6xxx_g2_switch_mac_write(chip, i, addr[i]);
169 /* Offset 0x0F: Priority Override Table */
171 static int mv88e6xxx_g2_pot_write(struct mv88e6xxx_chip *chip, int pointer,
174 u16 val = (pointer << 8) | (data & 0x7);
176 return mv88e6xxx_g2_update(chip, GLOBAL2_PRIO_OVERRIDE, val);
179 static int mv88e6xxx_g2_clear_pot(struct mv88e6xxx_chip *chip)
183 /* Clear all sixteen possible Priority Override entries */
184 for (i = 0; i < 16; i++) {
185 err = mv88e6xxx_g2_pot_write(chip, i, 0);
193 /* Offset 0x14: EEPROM Command
194 * Offset 0x15: EEPROM Data
197 static int mv88e6xxx_g2_eeprom_wait(struct mv88e6xxx_chip *chip)
199 return mv88e6xxx_g2_wait(chip, GLOBAL2_EEPROM_CMD,
200 GLOBAL2_EEPROM_CMD_BUSY |
201 GLOBAL2_EEPROM_CMD_RUNNING);
204 static int mv88e6xxx_g2_eeprom_cmd(struct mv88e6xxx_chip *chip, u16 cmd)
208 err = mv88e6xxx_g2_write(chip, GLOBAL2_EEPROM_CMD, cmd);
212 return mv88e6xxx_g2_eeprom_wait(chip);
215 static int mv88e6xxx_g2_eeprom_read16(struct mv88e6xxx_chip *chip,
218 u16 cmd = GLOBAL2_EEPROM_CMD_OP_READ | addr;
221 err = mv88e6xxx_g2_eeprom_wait(chip);
225 err = mv88e6xxx_g2_eeprom_cmd(chip, cmd);
229 return mv88e6xxx_g2_read(chip, GLOBAL2_EEPROM_DATA, data);
232 static int mv88e6xxx_g2_eeprom_write16(struct mv88e6xxx_chip *chip,
235 u16 cmd = GLOBAL2_EEPROM_CMD_OP_WRITE | addr;
238 err = mv88e6xxx_g2_eeprom_wait(chip);
242 err = mv88e6xxx_g2_write(chip, GLOBAL2_EEPROM_DATA, data);
246 return mv88e6xxx_g2_eeprom_cmd(chip, cmd);
249 int mv88e6xxx_g2_get_eeprom16(struct mv88e6xxx_chip *chip,
250 struct ethtool_eeprom *eeprom, u8 *data)
252 unsigned int offset = eeprom->offset;
253 unsigned int len = eeprom->len;
260 err = mv88e6xxx_g2_eeprom_read16(chip, offset >> 1, &val);
264 *data++ = (val >> 8) & 0xff;
272 err = mv88e6xxx_g2_eeprom_read16(chip, offset >> 1, &val);
276 *data++ = val & 0xff;
277 *data++ = (val >> 8) & 0xff;
285 err = mv88e6xxx_g2_eeprom_read16(chip, offset >> 1, &val);
289 *data++ = val & 0xff;
299 int mv88e6xxx_g2_set_eeprom16(struct mv88e6xxx_chip *chip,
300 struct ethtool_eeprom *eeprom, u8 *data)
302 unsigned int offset = eeprom->offset;
303 unsigned int len = eeprom->len;
307 /* Ensure the RO WriteEn bit is set */
308 err = mv88e6xxx_g2_read(chip, GLOBAL2_EEPROM_CMD, &val);
312 if (!(val & GLOBAL2_EEPROM_CMD_WRITE_EN))
318 err = mv88e6xxx_g2_eeprom_read16(chip, offset >> 1, &val);
322 val = (*data++ << 8) | (val & 0xff);
324 err = mv88e6xxx_g2_eeprom_write16(chip, offset >> 1, val);
337 err = mv88e6xxx_g2_eeprom_write16(chip, offset >> 1, val);
347 err = mv88e6xxx_g2_eeprom_read16(chip, offset >> 1, &val);
351 val = (val & 0xff00) | *data++;
353 err = mv88e6xxx_g2_eeprom_write16(chip, offset >> 1, val);
365 /* Offset 0x18: SMI PHY Command Register
366 * Offset 0x19: SMI PHY Data Register
369 static int mv88e6xxx_g2_smi_phy_wait(struct mv88e6xxx_chip *chip)
371 return mv88e6xxx_g2_wait(chip, GLOBAL2_SMI_PHY_CMD,
372 GLOBAL2_SMI_PHY_CMD_BUSY);
375 static int mv88e6xxx_g2_smi_phy_cmd(struct mv88e6xxx_chip *chip, u16 cmd)
379 err = mv88e6xxx_g2_write(chip, GLOBAL2_SMI_PHY_CMD, cmd);
383 return mv88e6xxx_g2_smi_phy_wait(chip);
386 int mv88e6xxx_g2_smi_phy_read(struct mv88e6xxx_chip *chip, int addr, int reg,
389 u16 cmd = GLOBAL2_SMI_PHY_CMD_OP_22_READ_DATA | (addr << 5) | reg;
392 err = mv88e6xxx_g2_smi_phy_wait(chip);
396 err = mv88e6xxx_g2_smi_phy_cmd(chip, cmd);
400 return mv88e6xxx_g2_read(chip, GLOBAL2_SMI_PHY_DATA, val);
403 int mv88e6xxx_g2_smi_phy_write(struct mv88e6xxx_chip *chip, int addr, int reg,
406 u16 cmd = GLOBAL2_SMI_PHY_CMD_OP_22_WRITE_DATA | (addr << 5) | reg;
409 err = mv88e6xxx_g2_smi_phy_wait(chip);
413 err = mv88e6xxx_g2_write(chip, GLOBAL2_SMI_PHY_DATA, val);
417 return mv88e6xxx_g2_smi_phy_cmd(chip, cmd);
420 int mv88e6xxx_g2_setup(struct mv88e6xxx_chip *chip)
425 if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_2X)) {
426 /* Consider the frames with reserved multicast destination
427 * addresses matching 01:80:c2:00:00:2x as MGMT.
429 err = mv88e6xxx_g2_write(chip, GLOBAL2_MGMT_EN_2X, 0xffff);
434 if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_0X)) {
435 /* Consider the frames with reserved multicast destination
436 * addresses matching 01:80:c2:00:00:0x as MGMT.
438 err = mv88e6xxx_g2_write(chip, GLOBAL2_MGMT_EN_0X, 0xffff);
443 /* Ignore removed tag data on doubly tagged packets, disable
444 * flow control messages, force flow control priority to the
445 * highest, and send all special multicast frames to the CPU
446 * port at the highest priority.
448 reg = GLOBAL2_SWITCH_MGMT_FORCE_FLOW_CTRL_PRI | (0x7 << 4);
449 if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_0X) ||
450 mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_2X))
451 reg |= GLOBAL2_SWITCH_MGMT_RSVD2CPU | 0x7;
452 err = mv88e6xxx_g2_write(chip, GLOBAL2_SWITCH_MGMT, reg);
456 /* Program the DSA routing table. */
457 err = mv88e6xxx_g2_set_device_mapping(chip);
461 /* Clear all trunk masks and mapping. */
462 err = mv88e6xxx_g2_clear_trunk(chip);
466 if (mv88e6xxx_has(chip, MV88E6XXX_FLAGS_IRL)) {
467 /* Disable ingress rate limiting by resetting all per port
468 * ingress rate limit resources to their initial state.
470 err = mv88e6xxx_g2_clear_irl(chip);
475 if (mv88e6xxx_has(chip, MV88E6XXX_FLAGS_PVT)) {
476 /* Initialize Cross-chip Port VLAN Table to reset defaults */
477 err = mv88e6xxx_g2_write(chip, GLOBAL2_PVT_ADDR,
478 GLOBAL2_PVT_ADDR_OP_INIT_ONES);
483 if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_POT)) {
484 /* Clear the priority override table. */
485 err = mv88e6xxx_g2_clear_pot(chip);