1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Marvell 88E6xxx Switch Global 2 Registers support
5 * Copyright (c) 2008 Marvell Semiconductor
7 * Copyright (c) 2016-2017 Savoir-faire Linux Inc.
8 * Vivien Didelot <vivien.didelot@savoirfairelinux.com>
11 #include <linux/bitfield.h>
12 #include <linux/interrupt.h>
13 #include <linux/irqdomain.h>
16 #include "global1.h" /* for MV88E6XXX_G1_STS_IRQ_DEVICE */
19 int mv88e6xxx_g2_read(struct mv88e6xxx_chip *chip, int reg, u16 *val)
21 return mv88e6xxx_read(chip, chip->info->global2_addr, reg, val);
24 int mv88e6xxx_g2_write(struct mv88e6xxx_chip *chip, int reg, u16 val)
26 return mv88e6xxx_write(chip, chip->info->global2_addr, reg, val);
29 int mv88e6xxx_g2_wait_bit(struct mv88e6xxx_chip *chip, int reg, int
32 return mv88e6xxx_wait_bit(chip, chip->info->global2_addr, reg,
36 /* Offset 0x00: Interrupt Source Register */
38 static int mv88e6xxx_g2_int_source(struct mv88e6xxx_chip *chip, u16 *src)
40 /* Read (and clear most of) the Interrupt Source bits */
41 return mv88e6xxx_g2_read(chip, MV88E6XXX_G2_INT_SRC, src);
44 /* Offset 0x01: Interrupt Mask Register */
46 static int mv88e6xxx_g2_int_mask(struct mv88e6xxx_chip *chip, u16 mask)
48 return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_INT_MASK, mask);
51 /* Offset 0x02: Management Enable 2x */
53 static int mv88e6xxx_g2_mgmt_enable_2x(struct mv88e6xxx_chip *chip, u16 en2x)
55 return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_MGMT_EN_2X, en2x);
58 /* Offset 0x03: Management Enable 0x */
60 static int mv88e6xxx_g2_mgmt_enable_0x(struct mv88e6xxx_chip *chip, u16 en0x)
62 return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_MGMT_EN_0X, en0x);
65 /* Offset 0x05: Switch Management Register */
67 static int mv88e6xxx_g2_switch_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip,
73 err = mv88e6xxx_g2_read(chip, MV88E6XXX_G2_SWITCH_MGMT, &val);
78 val |= MV88E6XXX_G2_SWITCH_MGMT_RSVD2CPU;
80 val &= ~MV88E6XXX_G2_SWITCH_MGMT_RSVD2CPU;
82 return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_SWITCH_MGMT, val);
85 int mv88e6185_g2_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip)
89 /* Consider the frames with reserved multicast destination
90 * addresses matching 01:80:c2:00:00:0x as MGMT.
92 err = mv88e6xxx_g2_mgmt_enable_0x(chip, 0xffff);
96 return mv88e6xxx_g2_switch_mgmt_rsvd2cpu(chip, true);
99 int mv88e6352_g2_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip)
103 /* Consider the frames with reserved multicast destination
104 * addresses matching 01:80:c2:00:00:2x as MGMT.
106 err = mv88e6xxx_g2_mgmt_enable_2x(chip, 0xffff);
110 return mv88e6185_g2_mgmt_rsvd2cpu(chip);
113 /* Offset 0x06: Device Mapping Table register */
115 int mv88e6xxx_g2_device_mapping_write(struct mv88e6xxx_chip *chip, int target,
118 u16 val = (target << 8) | (port & 0x1f);
119 /* Modern chips use 5 bits to define a device mapping port,
120 * but bit 4 is reserved on older chips, so it is safe to use.
123 return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_DEVICE_MAPPING,
124 MV88E6XXX_G2_DEVICE_MAPPING_UPDATE | val);
127 /* Offset 0x07: Trunk Mask Table register */
129 static int mv88e6xxx_g2_trunk_mask_write(struct mv88e6xxx_chip *chip, int num,
132 u16 val = (num << 12) | (mask & mv88e6xxx_port_mask(chip));
135 val |= MV88E6XXX_G2_TRUNK_MASK_HASH;
137 return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_TRUNK_MASK,
138 MV88E6XXX_G2_TRUNK_MASK_UPDATE | val);
141 /* Offset 0x08: Trunk Mapping Table register */
143 static int mv88e6xxx_g2_trunk_mapping_write(struct mv88e6xxx_chip *chip, int id,
146 const u16 port_mask = BIT(mv88e6xxx_num_ports(chip)) - 1;
147 u16 val = (id << 11) | (map & port_mask);
149 return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_TRUNK_MAPPING,
150 MV88E6XXX_G2_TRUNK_MAPPING_UPDATE | val);
153 int mv88e6xxx_g2_trunk_clear(struct mv88e6xxx_chip *chip)
155 const u16 port_mask = BIT(mv88e6xxx_num_ports(chip)) - 1;
158 /* Clear all eight possible Trunk Mask vectors */
159 for (i = 0; i < 8; ++i) {
160 err = mv88e6xxx_g2_trunk_mask_write(chip, i, false, port_mask);
165 /* Clear all sixteen possible Trunk ID routing vectors */
166 for (i = 0; i < 16; ++i) {
167 err = mv88e6xxx_g2_trunk_mapping_write(chip, i, 0);
175 /* Offset 0x09: Ingress Rate Command register
176 * Offset 0x0A: Ingress Rate Data register
179 static int mv88e6xxx_g2_irl_wait(struct mv88e6xxx_chip *chip)
181 int bit = __bf_shf(MV88E6XXX_G2_IRL_CMD_BUSY);
183 return mv88e6xxx_g2_wait_bit(chip, MV88E6XXX_G2_IRL_CMD, bit, 0);
186 static int mv88e6xxx_g2_irl_op(struct mv88e6xxx_chip *chip, u16 op, int port,
191 err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_IRL_CMD,
192 MV88E6XXX_G2_IRL_CMD_BUSY | op | (port << 8) |
197 return mv88e6xxx_g2_irl_wait(chip);
200 int mv88e6352_g2_irl_init_all(struct mv88e6xxx_chip *chip, int port)
202 return mv88e6xxx_g2_irl_op(chip, MV88E6352_G2_IRL_CMD_OP_INIT_ALL, port,
206 int mv88e6390_g2_irl_init_all(struct mv88e6xxx_chip *chip, int port)
208 return mv88e6xxx_g2_irl_op(chip, MV88E6390_G2_IRL_CMD_OP_INIT_ALL, port,
212 /* Offset 0x0B: Cross-chip Port VLAN (Addr) Register
213 * Offset 0x0C: Cross-chip Port VLAN Data Register
216 static int mv88e6xxx_g2_pvt_op_wait(struct mv88e6xxx_chip *chip)
218 int bit = __bf_shf(MV88E6XXX_G2_PVT_ADDR_BUSY);
220 return mv88e6xxx_g2_wait_bit(chip, MV88E6XXX_G2_PVT_ADDR, bit, 0);
223 static int mv88e6xxx_g2_pvt_op(struct mv88e6xxx_chip *chip, int src_dev,
224 int src_port, u16 op)
228 /* 9-bit Cross-chip PVT pointer: with MV88E6XXX_G2_MISC_5_BIT_PORT
229 * cleared, source device is 5-bit, source port is 4-bit.
231 op |= MV88E6XXX_G2_PVT_ADDR_BUSY;
232 op |= (src_dev & 0x1f) << 4;
233 op |= (src_port & 0xf);
235 err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_PVT_ADDR, op);
239 return mv88e6xxx_g2_pvt_op_wait(chip);
242 int mv88e6xxx_g2_pvt_write(struct mv88e6xxx_chip *chip, int src_dev,
243 int src_port, u16 data)
247 err = mv88e6xxx_g2_pvt_op_wait(chip);
251 err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_PVT_DATA, data);
255 return mv88e6xxx_g2_pvt_op(chip, src_dev, src_port,
256 MV88E6XXX_G2_PVT_ADDR_OP_WRITE_PVLAN);
259 /* Offset 0x0D: Switch MAC/WoL/WoF register */
261 static int mv88e6xxx_g2_switch_mac_write(struct mv88e6xxx_chip *chip,
262 unsigned int pointer, u8 data)
264 u16 val = (pointer << 8) | data;
266 return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_SWITCH_MAC,
267 MV88E6XXX_G2_SWITCH_MAC_UPDATE | val);
270 int mv88e6xxx_g2_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr)
274 for (i = 0; i < 6; i++) {
275 err = mv88e6xxx_g2_switch_mac_write(chip, i, addr[i]);
283 /* Offset 0x0E: ATU Statistics */
285 int mv88e6xxx_g2_atu_stats_set(struct mv88e6xxx_chip *chip, u16 kind, u16 bin)
287 return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_ATU_STATS,
291 int mv88e6xxx_g2_atu_stats_get(struct mv88e6xxx_chip *chip, u16 *stats)
293 return mv88e6xxx_g2_read(chip, MV88E6XXX_G2_ATU_STATS, stats);
296 /* Offset 0x0F: Priority Override Table */
298 static int mv88e6xxx_g2_pot_write(struct mv88e6xxx_chip *chip, int pointer,
301 u16 val = (pointer << 8) | (data & 0x7);
303 return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_PRIO_OVERRIDE,
304 MV88E6XXX_G2_PRIO_OVERRIDE_UPDATE | val);
307 int mv88e6xxx_g2_pot_clear(struct mv88e6xxx_chip *chip)
311 /* Clear all sixteen possible Priority Override entries */
312 for (i = 0; i < 16; i++) {
313 err = mv88e6xxx_g2_pot_write(chip, i, 0);
321 /* Offset 0x14: EEPROM Command
322 * Offset 0x15: EEPROM Data (for 16-bit data access)
323 * Offset 0x15: EEPROM Addr (for 8-bit data access)
326 static int mv88e6xxx_g2_eeprom_wait(struct mv88e6xxx_chip *chip)
328 int bit = __bf_shf(MV88E6XXX_G2_EEPROM_CMD_BUSY);
331 err = mv88e6xxx_g2_wait_bit(chip, MV88E6XXX_G2_EEPROM_CMD, bit, 0);
335 bit = __bf_shf(MV88E6XXX_G2_EEPROM_CMD_RUNNING);
337 return mv88e6xxx_g2_wait_bit(chip, MV88E6XXX_G2_EEPROM_CMD, bit, 0);
340 static int mv88e6xxx_g2_eeprom_cmd(struct mv88e6xxx_chip *chip, u16 cmd)
344 err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_EEPROM_CMD,
345 MV88E6XXX_G2_EEPROM_CMD_BUSY | cmd);
349 return mv88e6xxx_g2_eeprom_wait(chip);
352 static int mv88e6xxx_g2_eeprom_read8(struct mv88e6xxx_chip *chip,
355 u16 cmd = MV88E6XXX_G2_EEPROM_CMD_OP_READ;
358 err = mv88e6xxx_g2_eeprom_wait(chip);
362 err = mv88e6xxx_g2_write(chip, MV88E6390_G2_EEPROM_ADDR, addr);
366 err = mv88e6xxx_g2_eeprom_cmd(chip, cmd);
370 err = mv88e6xxx_g2_read(chip, MV88E6XXX_G2_EEPROM_CMD, &cmd);
379 static int mv88e6xxx_g2_eeprom_write8(struct mv88e6xxx_chip *chip,
382 u16 cmd = MV88E6XXX_G2_EEPROM_CMD_OP_WRITE |
383 MV88E6XXX_G2_EEPROM_CMD_WRITE_EN;
386 err = mv88e6xxx_g2_eeprom_wait(chip);
390 err = mv88e6xxx_g2_write(chip, MV88E6390_G2_EEPROM_ADDR, addr);
394 return mv88e6xxx_g2_eeprom_cmd(chip, cmd | data);
397 static int mv88e6xxx_g2_eeprom_read16(struct mv88e6xxx_chip *chip,
400 u16 cmd = MV88E6XXX_G2_EEPROM_CMD_OP_READ | addr;
403 err = mv88e6xxx_g2_eeprom_wait(chip);
407 err = mv88e6xxx_g2_eeprom_cmd(chip, cmd);
411 return mv88e6xxx_g2_read(chip, MV88E6352_G2_EEPROM_DATA, data);
414 static int mv88e6xxx_g2_eeprom_write16(struct mv88e6xxx_chip *chip,
417 u16 cmd = MV88E6XXX_G2_EEPROM_CMD_OP_WRITE | addr;
420 err = mv88e6xxx_g2_eeprom_wait(chip);
424 err = mv88e6xxx_g2_write(chip, MV88E6352_G2_EEPROM_DATA, data);
428 return mv88e6xxx_g2_eeprom_cmd(chip, cmd);
431 int mv88e6xxx_g2_get_eeprom8(struct mv88e6xxx_chip *chip,
432 struct ethtool_eeprom *eeprom, u8 *data)
434 unsigned int offset = eeprom->offset;
435 unsigned int len = eeprom->len;
441 err = mv88e6xxx_g2_eeprom_read8(chip, offset, data);
454 int mv88e6xxx_g2_set_eeprom8(struct mv88e6xxx_chip *chip,
455 struct ethtool_eeprom *eeprom, u8 *data)
457 unsigned int offset = eeprom->offset;
458 unsigned int len = eeprom->len;
464 err = mv88e6xxx_g2_eeprom_write8(chip, offset, *data);
477 int mv88e6xxx_g2_get_eeprom16(struct mv88e6xxx_chip *chip,
478 struct ethtool_eeprom *eeprom, u8 *data)
480 unsigned int offset = eeprom->offset;
481 unsigned int len = eeprom->len;
488 err = mv88e6xxx_g2_eeprom_read16(chip, offset >> 1, &val);
492 *data++ = (val >> 8) & 0xff;
500 err = mv88e6xxx_g2_eeprom_read16(chip, offset >> 1, &val);
504 *data++ = val & 0xff;
505 *data++ = (val >> 8) & 0xff;
513 err = mv88e6xxx_g2_eeprom_read16(chip, offset >> 1, &val);
517 *data++ = val & 0xff;
527 int mv88e6xxx_g2_set_eeprom16(struct mv88e6xxx_chip *chip,
528 struct ethtool_eeprom *eeprom, u8 *data)
530 unsigned int offset = eeprom->offset;
531 unsigned int len = eeprom->len;
535 /* Ensure the RO WriteEn bit is set */
536 err = mv88e6xxx_g2_read(chip, MV88E6XXX_G2_EEPROM_CMD, &val);
540 if (!(val & MV88E6XXX_G2_EEPROM_CMD_WRITE_EN))
546 err = mv88e6xxx_g2_eeprom_read16(chip, offset >> 1, &val);
550 val = (*data++ << 8) | (val & 0xff);
552 err = mv88e6xxx_g2_eeprom_write16(chip, offset >> 1, val);
565 err = mv88e6xxx_g2_eeprom_write16(chip, offset >> 1, val);
575 err = mv88e6xxx_g2_eeprom_read16(chip, offset >> 1, &val);
579 val = (val & 0xff00) | *data++;
581 err = mv88e6xxx_g2_eeprom_write16(chip, offset >> 1, val);
593 /* Offset 0x18: SMI PHY Command Register
594 * Offset 0x19: SMI PHY Data Register
597 static int mv88e6xxx_g2_smi_phy_wait(struct mv88e6xxx_chip *chip)
599 int bit = __bf_shf(MV88E6XXX_G2_SMI_PHY_CMD_BUSY);
601 return mv88e6xxx_g2_wait_bit(chip, MV88E6XXX_G2_SMI_PHY_CMD, bit, 0);
604 static int mv88e6xxx_g2_smi_phy_cmd(struct mv88e6xxx_chip *chip, u16 cmd)
608 err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_SMI_PHY_CMD,
609 MV88E6XXX_G2_SMI_PHY_CMD_BUSY | cmd);
613 return mv88e6xxx_g2_smi_phy_wait(chip);
616 static int mv88e6xxx_g2_smi_phy_access(struct mv88e6xxx_chip *chip,
617 bool external, bool c45, u16 op, int dev,
623 cmd |= MV88E6390_G2_SMI_PHY_CMD_FUNC_EXTERNAL;
625 cmd |= MV88E6390_G2_SMI_PHY_CMD_FUNC_INTERNAL; /* empty mask */
628 cmd |= MV88E6XXX_G2_SMI_PHY_CMD_MODE_45; /* empty mask */
630 cmd |= MV88E6XXX_G2_SMI_PHY_CMD_MODE_22;
632 dev <<= __bf_shf(MV88E6XXX_G2_SMI_PHY_CMD_DEV_ADDR_MASK);
633 cmd |= dev & MV88E6XXX_G2_SMI_PHY_CMD_DEV_ADDR_MASK;
634 cmd |= reg & MV88E6XXX_G2_SMI_PHY_CMD_REG_ADDR_MASK;
636 return mv88e6xxx_g2_smi_phy_cmd(chip, cmd);
639 static int mv88e6xxx_g2_smi_phy_access_c22(struct mv88e6xxx_chip *chip,
640 bool external, u16 op, int dev,
643 return mv88e6xxx_g2_smi_phy_access(chip, external, false, op, dev, reg);
646 /* IEEE 802.3 Clause 22 Read Data Register */
647 static int mv88e6xxx_g2_smi_phy_read_data_c22(struct mv88e6xxx_chip *chip,
648 bool external, int dev, int reg,
651 u16 op = MV88E6XXX_G2_SMI_PHY_CMD_OP_22_READ_DATA;
654 err = mv88e6xxx_g2_smi_phy_wait(chip);
658 err = mv88e6xxx_g2_smi_phy_access_c22(chip, external, op, dev, reg);
662 return mv88e6xxx_g2_read(chip, MV88E6XXX_G2_SMI_PHY_DATA, data);
665 /* IEEE 802.3 Clause 22 Write Data Register */
666 static int mv88e6xxx_g2_smi_phy_write_data_c22(struct mv88e6xxx_chip *chip,
667 bool external, int dev, int reg,
670 u16 op = MV88E6XXX_G2_SMI_PHY_CMD_OP_22_WRITE_DATA;
673 err = mv88e6xxx_g2_smi_phy_wait(chip);
677 err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_SMI_PHY_DATA, data);
681 return mv88e6xxx_g2_smi_phy_access_c22(chip, external, op, dev, reg);
684 static int mv88e6xxx_g2_smi_phy_access_c45(struct mv88e6xxx_chip *chip,
685 bool external, u16 op, int port,
688 return mv88e6xxx_g2_smi_phy_access(chip, external, true, op, port, dev);
691 /* IEEE 802.3 Clause 45 Write Address Register */
692 static int mv88e6xxx_g2_smi_phy_write_addr_c45(struct mv88e6xxx_chip *chip,
693 bool external, int port, int dev,
696 u16 op = MV88E6XXX_G2_SMI_PHY_CMD_OP_45_WRITE_ADDR;
699 err = mv88e6xxx_g2_smi_phy_wait(chip);
703 err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_SMI_PHY_DATA, addr);
707 return mv88e6xxx_g2_smi_phy_access_c45(chip, external, op, port, dev);
710 /* IEEE 802.3 Clause 45 Read Data Register */
711 static int mv88e6xxx_g2_smi_phy_read_data_c45(struct mv88e6xxx_chip *chip,
712 bool external, int port, int dev,
715 u16 op = MV88E6XXX_G2_SMI_PHY_CMD_OP_45_READ_DATA;
718 err = mv88e6xxx_g2_smi_phy_access_c45(chip, external, op, port, dev);
722 return mv88e6xxx_g2_read(chip, MV88E6XXX_G2_SMI_PHY_DATA, data);
725 static int mv88e6xxx_g2_smi_phy_read_c45(struct mv88e6xxx_chip *chip,
726 bool external, int port, int reg,
729 int dev = (reg >> 16) & 0x1f;
730 int addr = reg & 0xffff;
733 err = mv88e6xxx_g2_smi_phy_write_addr_c45(chip, external, port, dev,
738 return mv88e6xxx_g2_smi_phy_read_data_c45(chip, external, port, dev,
742 /* IEEE 802.3 Clause 45 Write Data Register */
743 static int mv88e6xxx_g2_smi_phy_write_data_c45(struct mv88e6xxx_chip *chip,
744 bool external, int port, int dev,
747 u16 op = MV88E6XXX_G2_SMI_PHY_CMD_OP_45_WRITE_DATA;
750 err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_SMI_PHY_DATA, data);
754 return mv88e6xxx_g2_smi_phy_access_c45(chip, external, op, port, dev);
757 static int mv88e6xxx_g2_smi_phy_write_c45(struct mv88e6xxx_chip *chip,
758 bool external, int port, int reg,
761 int dev = (reg >> 16) & 0x1f;
762 int addr = reg & 0xffff;
765 err = mv88e6xxx_g2_smi_phy_write_addr_c45(chip, external, port, dev,
770 return mv88e6xxx_g2_smi_phy_write_data_c45(chip, external, port, dev,
774 int mv88e6xxx_g2_smi_phy_read(struct mv88e6xxx_chip *chip, struct mii_bus *bus,
775 int addr, int reg, u16 *val)
777 struct mv88e6xxx_mdio_bus *mdio_bus = bus->priv;
778 bool external = mdio_bus->external;
780 if (reg & MII_ADDR_C45)
781 return mv88e6xxx_g2_smi_phy_read_c45(chip, external, addr, reg,
784 return mv88e6xxx_g2_smi_phy_read_data_c22(chip, external, addr, reg,
788 int mv88e6xxx_g2_smi_phy_write(struct mv88e6xxx_chip *chip, struct mii_bus *bus,
789 int addr, int reg, u16 val)
791 struct mv88e6xxx_mdio_bus *mdio_bus = bus->priv;
792 bool external = mdio_bus->external;
794 if (reg & MII_ADDR_C45)
795 return mv88e6xxx_g2_smi_phy_write_c45(chip, external, addr, reg,
798 return mv88e6xxx_g2_smi_phy_write_data_c22(chip, external, addr, reg,
802 /* Offset 0x1B: Watchdog Control */
803 static int mv88e6097_watchdog_action(struct mv88e6xxx_chip *chip, int irq)
807 mv88e6xxx_g2_read(chip, MV88E6352_G2_WDOG_CTL, ®);
809 dev_info(chip->dev, "Watchdog event: 0x%04x", reg);
814 static void mv88e6097_watchdog_free(struct mv88e6xxx_chip *chip)
818 mv88e6xxx_g2_read(chip, MV88E6352_G2_WDOG_CTL, ®);
820 reg &= ~(MV88E6352_G2_WDOG_CTL_EGRESS_ENABLE |
821 MV88E6352_G2_WDOG_CTL_QC_ENABLE);
823 mv88e6xxx_g2_write(chip, MV88E6352_G2_WDOG_CTL, reg);
826 static int mv88e6097_watchdog_setup(struct mv88e6xxx_chip *chip)
828 return mv88e6xxx_g2_write(chip, MV88E6352_G2_WDOG_CTL,
829 MV88E6352_G2_WDOG_CTL_EGRESS_ENABLE |
830 MV88E6352_G2_WDOG_CTL_QC_ENABLE |
831 MV88E6352_G2_WDOG_CTL_SWRESET);
834 const struct mv88e6xxx_irq_ops mv88e6097_watchdog_ops = {
835 .irq_action = mv88e6097_watchdog_action,
836 .irq_setup = mv88e6097_watchdog_setup,
837 .irq_free = mv88e6097_watchdog_free,
840 static void mv88e6250_watchdog_free(struct mv88e6xxx_chip *chip)
844 mv88e6xxx_g2_read(chip, MV88E6250_G2_WDOG_CTL, ®);
846 reg &= ~(MV88E6250_G2_WDOG_CTL_EGRESS_ENABLE |
847 MV88E6250_G2_WDOG_CTL_QC_ENABLE);
849 mv88e6xxx_g2_write(chip, MV88E6250_G2_WDOG_CTL, reg);
852 static int mv88e6250_watchdog_setup(struct mv88e6xxx_chip *chip)
854 return mv88e6xxx_g2_write(chip, MV88E6250_G2_WDOG_CTL,
855 MV88E6250_G2_WDOG_CTL_EGRESS_ENABLE |
856 MV88E6250_G2_WDOG_CTL_QC_ENABLE |
857 MV88E6250_G2_WDOG_CTL_SWRESET);
860 const struct mv88e6xxx_irq_ops mv88e6250_watchdog_ops = {
861 .irq_action = mv88e6097_watchdog_action,
862 .irq_setup = mv88e6250_watchdog_setup,
863 .irq_free = mv88e6250_watchdog_free,
866 static int mv88e6390_watchdog_setup(struct mv88e6xxx_chip *chip)
868 return mv88e6xxx_g2_write(chip, MV88E6390_G2_WDOG_CTL,
869 MV88E6390_G2_WDOG_CTL_UPDATE |
870 MV88E6390_G2_WDOG_CTL_PTR_INT_ENABLE |
871 MV88E6390_G2_WDOG_CTL_CUT_THROUGH |
872 MV88E6390_G2_WDOG_CTL_QUEUE_CONTROLLER |
873 MV88E6390_G2_WDOG_CTL_EGRESS |
874 MV88E6390_G2_WDOG_CTL_FORCE_IRQ);
877 static int mv88e6390_watchdog_action(struct mv88e6xxx_chip *chip, int irq)
882 mv88e6xxx_g2_write(chip, MV88E6390_G2_WDOG_CTL,
883 MV88E6390_G2_WDOG_CTL_PTR_EVENT);
884 err = mv88e6xxx_g2_read(chip, MV88E6390_G2_WDOG_CTL, ®);
886 dev_info(chip->dev, "Watchdog event: 0x%04x",
887 reg & MV88E6390_G2_WDOG_CTL_DATA_MASK);
889 mv88e6xxx_g2_write(chip, MV88E6390_G2_WDOG_CTL,
890 MV88E6390_G2_WDOG_CTL_PTR_HISTORY);
891 err = mv88e6xxx_g2_read(chip, MV88E6390_G2_WDOG_CTL, ®);
893 dev_info(chip->dev, "Watchdog history: 0x%04x",
894 reg & MV88E6390_G2_WDOG_CTL_DATA_MASK);
896 /* Trigger a software reset to try to recover the switch */
897 if (chip->info->ops->reset)
898 chip->info->ops->reset(chip);
900 mv88e6390_watchdog_setup(chip);
905 static void mv88e6390_watchdog_free(struct mv88e6xxx_chip *chip)
907 mv88e6xxx_g2_write(chip, MV88E6390_G2_WDOG_CTL,
908 MV88E6390_G2_WDOG_CTL_UPDATE |
909 MV88E6390_G2_WDOG_CTL_PTR_INT_ENABLE);
912 const struct mv88e6xxx_irq_ops mv88e6390_watchdog_ops = {
913 .irq_action = mv88e6390_watchdog_action,
914 .irq_setup = mv88e6390_watchdog_setup,
915 .irq_free = mv88e6390_watchdog_free,
918 static irqreturn_t mv88e6xxx_g2_watchdog_thread_fn(int irq, void *dev_id)
920 struct mv88e6xxx_chip *chip = dev_id;
921 irqreturn_t ret = IRQ_NONE;
923 mv88e6xxx_reg_lock(chip);
924 if (chip->info->ops->watchdog_ops->irq_action)
925 ret = chip->info->ops->watchdog_ops->irq_action(chip, irq);
926 mv88e6xxx_reg_unlock(chip);
931 static void mv88e6xxx_g2_watchdog_free(struct mv88e6xxx_chip *chip)
933 mv88e6xxx_reg_lock(chip);
934 if (chip->info->ops->watchdog_ops->irq_free)
935 chip->info->ops->watchdog_ops->irq_free(chip);
936 mv88e6xxx_reg_unlock(chip);
938 free_irq(chip->watchdog_irq, chip);
939 irq_dispose_mapping(chip->watchdog_irq);
942 static int mv88e6xxx_g2_watchdog_setup(struct mv88e6xxx_chip *chip)
946 chip->watchdog_irq = irq_find_mapping(chip->g2_irq.domain,
947 MV88E6XXX_G2_INT_SOURCE_WATCHDOG);
948 if (chip->watchdog_irq < 0)
949 return chip->watchdog_irq;
951 snprintf(chip->watchdog_irq_name, sizeof(chip->watchdog_irq_name),
952 "mv88e6xxx-%s-watchdog", dev_name(chip->dev));
954 err = request_threaded_irq(chip->watchdog_irq, NULL,
955 mv88e6xxx_g2_watchdog_thread_fn,
956 IRQF_ONESHOT | IRQF_TRIGGER_FALLING,
957 chip->watchdog_irq_name, chip);
961 mv88e6xxx_reg_lock(chip);
962 if (chip->info->ops->watchdog_ops->irq_setup)
963 err = chip->info->ops->watchdog_ops->irq_setup(chip);
964 mv88e6xxx_reg_unlock(chip);
969 /* Offset 0x1D: Misc Register */
971 static int mv88e6xxx_g2_misc_5_bit_port(struct mv88e6xxx_chip *chip,
977 err = mv88e6xxx_g2_read(chip, MV88E6XXX_G2_MISC, &val);
982 val |= MV88E6XXX_G2_MISC_5_BIT_PORT;
984 val &= ~MV88E6XXX_G2_MISC_5_BIT_PORT;
986 return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_MISC, val);
989 int mv88e6xxx_g2_misc_4_bit_port(struct mv88e6xxx_chip *chip)
991 return mv88e6xxx_g2_misc_5_bit_port(chip, false);
994 static void mv88e6xxx_g2_irq_mask(struct irq_data *d)
996 struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
997 unsigned int n = d->hwirq;
999 chip->g2_irq.masked |= (1 << n);
1002 static void mv88e6xxx_g2_irq_unmask(struct irq_data *d)
1004 struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
1005 unsigned int n = d->hwirq;
1007 chip->g2_irq.masked &= ~(1 << n);
1010 static irqreturn_t mv88e6xxx_g2_irq_thread_fn(int irq, void *dev_id)
1012 struct mv88e6xxx_chip *chip = dev_id;
1013 unsigned int nhandled = 0;
1014 unsigned int sub_irq;
1019 mv88e6xxx_reg_lock(chip);
1020 err = mv88e6xxx_g2_int_source(chip, ®);
1021 mv88e6xxx_reg_unlock(chip);
1025 for (n = 0; n < 16; ++n) {
1026 if (reg & (1 << n)) {
1027 sub_irq = irq_find_mapping(chip->g2_irq.domain, n);
1028 handle_nested_irq(sub_irq);
1033 return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE);
1036 static void mv88e6xxx_g2_irq_bus_lock(struct irq_data *d)
1038 struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
1040 mv88e6xxx_reg_lock(chip);
1043 static void mv88e6xxx_g2_irq_bus_sync_unlock(struct irq_data *d)
1045 struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
1048 err = mv88e6xxx_g2_int_mask(chip, ~chip->g2_irq.masked);
1050 dev_err(chip->dev, "failed to mask interrupts\n");
1052 mv88e6xxx_reg_unlock(chip);
1055 static const struct irq_chip mv88e6xxx_g2_irq_chip = {
1056 .name = "mv88e6xxx-g2",
1057 .irq_mask = mv88e6xxx_g2_irq_mask,
1058 .irq_unmask = mv88e6xxx_g2_irq_unmask,
1059 .irq_bus_lock = mv88e6xxx_g2_irq_bus_lock,
1060 .irq_bus_sync_unlock = mv88e6xxx_g2_irq_bus_sync_unlock,
1063 static int mv88e6xxx_g2_irq_domain_map(struct irq_domain *d,
1065 irq_hw_number_t hwirq)
1067 struct mv88e6xxx_chip *chip = d->host_data;
1069 irq_set_chip_data(irq, d->host_data);
1070 irq_set_chip_and_handler(irq, &chip->g2_irq.chip, handle_level_irq);
1071 irq_set_noprobe(irq);
1076 static const struct irq_domain_ops mv88e6xxx_g2_irq_domain_ops = {
1077 .map = mv88e6xxx_g2_irq_domain_map,
1078 .xlate = irq_domain_xlate_twocell,
1081 void mv88e6xxx_g2_irq_free(struct mv88e6xxx_chip *chip)
1085 mv88e6xxx_g2_watchdog_free(chip);
1087 free_irq(chip->device_irq, chip);
1088 irq_dispose_mapping(chip->device_irq);
1090 for (irq = 0; irq < 16; irq++) {
1091 virq = irq_find_mapping(chip->g2_irq.domain, irq);
1092 irq_dispose_mapping(virq);
1095 irq_domain_remove(chip->g2_irq.domain);
1098 int mv88e6xxx_g2_irq_setup(struct mv88e6xxx_chip *chip)
1102 chip->g2_irq.domain = irq_domain_add_simple(
1103 chip->dev->of_node, 16, 0, &mv88e6xxx_g2_irq_domain_ops, chip);
1104 if (!chip->g2_irq.domain)
1107 for (irq = 0; irq < 16; irq++)
1108 irq_create_mapping(chip->g2_irq.domain, irq);
1110 chip->g2_irq.chip = mv88e6xxx_g2_irq_chip;
1111 chip->g2_irq.masked = ~0;
1113 chip->device_irq = irq_find_mapping(chip->g1_irq.domain,
1114 MV88E6XXX_G1_STS_IRQ_DEVICE);
1115 if (chip->device_irq < 0) {
1116 err = chip->device_irq;
1120 snprintf(chip->device_irq_name, sizeof(chip->device_irq_name),
1121 "mv88e6xxx-%s-g2", dev_name(chip->dev));
1123 err = request_threaded_irq(chip->device_irq, NULL,
1124 mv88e6xxx_g2_irq_thread_fn,
1125 IRQF_ONESHOT, chip->device_irq_name, chip);
1129 return mv88e6xxx_g2_watchdog_setup(chip);
1132 for (irq = 0; irq < 16; irq++) {
1133 virq = irq_find_mapping(chip->g2_irq.domain, irq);
1134 irq_dispose_mapping(virq);
1137 irq_domain_remove(chip->g2_irq.domain);
1142 int mv88e6xxx_g2_irq_mdio_setup(struct mv88e6xxx_chip *chip,
1143 struct mii_bus *bus)
1145 int phy, irq, err, err_phy;
1147 for (phy = 0; phy < chip->info->num_internal_phys; phy++) {
1148 irq = irq_find_mapping(chip->g2_irq.domain, phy);
1153 bus->irq[chip->info->phy_base_addr + phy] = irq;
1159 for (phy = 0; phy < err_phy; phy++)
1160 irq_dispose_mapping(bus->irq[phy]);
1165 void mv88e6xxx_g2_irq_mdio_free(struct mv88e6xxx_chip *chip,
1166 struct mii_bus *bus)
1170 for (phy = 0; phy < chip->info->num_internal_phys; phy++)
1171 irq_dispose_mapping(bus->irq[phy]);