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