// SPDX-License-Identifier: GPL-2.0-or-later /* * Marvell 88E6xxx Switch Global (1) Registers support * * Copyright (c) 2008 Marvell Semiconductor * * Copyright (c) 2016-2017 Savoir-faire Linux Inc. * Vivien Didelot <vivien.didelot@savoirfairelinux.com>
*/
#include <linux/bitfield.h>
#include"chip.h" #include"global1.h"
int mv88e6xxx_g1_read(struct mv88e6xxx_chip *chip, int reg, u16 *val)
{ int addr = chip->info->global1_addr;
return mv88e6xxx_read(chip, addr, reg, val);
}
int mv88e6xxx_g1_write(struct mv88e6xxx_chip *chip, int reg, u16 val)
{ int addr = chip->info->global1_addr;
return mv88e6xxx_write(chip, addr, reg, val);
}
int mv88e6xxx_g1_wait_bit(struct mv88e6xxx_chip *chip, int reg, int
bit, int val)
{ return mv88e6xxx_wait_bit(chip, chip->info->global1_addr, reg,
bit, val);
}
int mv88e6xxx_g1_wait_mask(struct mv88e6xxx_chip *chip, int reg,
u16 mask, u16 val)
{ return mv88e6xxx_wait_mask(chip, chip->info->global1_addr, reg,
mask, val);
}
staticint mv88e6xxx_g1_wait_init_ready(struct mv88e6xxx_chip *chip)
{ int bit = __bf_shf(MV88E6XXX_G1_STS_INIT_READY);
/* Wait up to 1 second for the switch to be ready. The InitReady bit 11 * is set to a one when all units inside the device (ATU, VTU, etc.) * have finished their initialization and are ready to accept frames.
*/ return mv88e6xxx_g1_wait_bit(chip, MV88E6XXX_G1_STS, bit, 1);
}
staticint mv88e6250_g1_eeprom_reload(struct mv88e6xxx_chip *chip)
{ /* MV88E6185_G1_CTL1_RELOAD_EEPROM is also valid for 88E6250 */ int bit = __bf_shf(MV88E6185_G1_CTL1_RELOAD_EEPROM);
u16 val; int err;
err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &val); if (err) return err;
val |= MV88E6185_G1_CTL1_RELOAD_EEPROM;
err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, val); if (err) return err;
/* Returns 0 when done, -EBUSY when waiting, other negative codes on error */ staticint mv88e6xxx_g1_is_eeprom_done(struct mv88e6xxx_chip *chip)
{
u16 val; int err;
/* If the switch is still resetting, it may not * respond on the bus, and so MDIO read returns * 0xffff. Differentiate between that, and waiting for * the EEPROM to be done by bit 0 being set.
*/ if (val == 0xffff || !(val & BIT(MV88E6XXX_G1_STS_IRQ_EEPROM_DONE))) return -EBUSY;
return 0;
}
/* As the EEInt (EEPROM done) flag clears on read if the status register, this * function must be called directly after a hard reset or EEPROM ReLoad request, * or the done condition may have been missed
*/ int mv88e6xxx_g1_wait_eeprom_done(struct mv88e6xxx_chip *chip)
{ constunsignedlong timeout = jiffies + 1 * HZ; int ret;
/* Wait up to 1 second for the switch to finish reading the * EEPROM.
*/ while (time_before(jiffies, timeout)) {
ret = mv88e6xxx_g1_is_eeprom_done(chip); if (ret != -EBUSY) return ret;
}
dev_err(chip->dev, "Timeout waiting for EEPROM done"); return -ETIMEDOUT;
}
int mv88e6250_g1_wait_eeprom_done_prereset(struct mv88e6xxx_chip *chip)
{ int ret;
ret = mv88e6xxx_g1_is_eeprom_done(chip); if (ret != -EBUSY) return ret;
/* Pre-reset, we don't know the state of the switch - when * mv88e6xxx_g1_is_eeprom_done() returns -EBUSY, that may be because * the switch is actually busy reading the EEPROM, or because * MV88E6XXX_G1_STS_IRQ_EEPROM_DONE has been cleared by an unrelated * status register read already. * * To account for the latter case, trigger another EEPROM reload for * another chance at seeing the done flag.
*/
ret = mv88e6250_g1_eeprom_reload(chip); if (ret) return ret;
return mv88e6xxx_g1_wait_eeprom_done(chip);
}
/* Offset 0x01: Switch MAC Address Register Bytes 0 & 1 * Offset 0x02: Switch MAC Address Register Bytes 2 & 3 * Offset 0x03: Switch MAC Address Register Bytes 4 & 5
*/ int mv88e6xxx_g1_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr)
{
u16 reg; int err;
int mv88e6185_g1_reset(struct mv88e6xxx_chip *chip)
{
u16 val; int err;
/* Set the SWReset bit 15 along with the PPUEn bit 14, to also restart * the PPU, including re-doing PHY detection and initialization
*/
err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &val); if (err) return err;
val |= MV88E6XXX_G1_CTL1_SW_RESET;
val |= MV88E6XXX_G1_CTL1_PPU_ENABLE;
err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, val); if (err) return err;
err = mv88e6xxx_g1_wait_init_ready(chip); if (err) return err;
return mv88e6185_g1_wait_ppu_polling(chip);
}
int mv88e6250_g1_reset(struct mv88e6xxx_chip *chip)
{
u16 val; int err;
/* Set the SWReset bit 15 */
err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &val); if (err) return err;
val |= MV88E6XXX_G1_CTL1_SW_RESET;
err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, val); if (err) return err;
return mv88e6xxx_g1_wait_init_ready(chip);
}
int mv88e6352_g1_reset(struct mv88e6xxx_chip *chip)
{ int err;
err = mv88e6250_g1_reset(chip); if (err) return err;
return mv88e6352_g1_wait_ppu_polling(chip);
}
int mv88e6185_g1_ppu_enable(struct mv88e6xxx_chip *chip)
{
u16 val; int err;
err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &val); if (err) return err;
val |= MV88E6XXX_G1_CTL1_PPU_ENABLE;
err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, val); if (err) return err;
return mv88e6185_g1_wait_ppu_polling(chip);
}
int mv88e6185_g1_ppu_disable(struct mv88e6xxx_chip *chip)
{
u16 val; int err;
err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &val); if (err) return err;
val &= ~MV88E6XXX_G1_CTL1_PPU_ENABLE;
err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, val); if (err) return err;
return mv88e6185_g1_wait_ppu_disabled(chip);
}
int mv88e6185_g1_set_max_frame_size(struct mv88e6xxx_chip *chip, int mtu)
{
u16 val; int err;
mtu += ETH_HLEN + ETH_FCS_LEN;
err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &val); if (err) return err;
val &= ~MV88E6185_G1_CTL1_MAX_FRAME_1632;
if (mtu > 1518)
val |= MV88E6185_G1_CTL1_MAX_FRAME_1632;
int mv88e6085_g1_ip_pri_map(struct mv88e6xxx_chip *chip)
{ int err;
/* Reset the IP TOS/DiffServ/Traffic priorities to defaults */
err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_IP_PRI_0, 0x0000); if (err) return err;
err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_IP_PRI_1, 0x0000); if (err) return err;
err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_IP_PRI_2, 0x5555); if (err) return err;
err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_IP_PRI_3, 0x5555); if (err) return err;
err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_IP_PRI_4, 0xaaaa); if (err) return err;
err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_IP_PRI_5, 0xaaaa); if (err) return err;
err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_IP_PRI_6, 0xffff); if (err) return err;
err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_IP_PRI_7, 0xffff); if (err) return err;
return 0;
}
/* Offset 0x18: IEEE-PRI Register */
int mv88e6085_g1_ieee_pri_map(struct mv88e6xxx_chip *chip)
{ /* Reset the IEEE Tag priorities to defaults */ return mv88e6xxx_g1_write(chip, MV88E6XXX_G1_IEEE_PRI, 0xfa41);
}
int mv88e6250_g1_ieee_pri_map(struct mv88e6xxx_chip *chip)
{ /* Reset the IEEE Tag priorities to defaults */ return mv88e6xxx_g1_write(chip, MV88E6XXX_G1_IEEE_PRI, 0xfa50);
}
/* Offset 0x1a: Monitor Control */ /* Offset 0x1a: Monitor & MGMT Control on some devices */
int mv88e6095_g1_set_egress_port(struct mv88e6xxx_chip *chip, enum mv88e6xxx_egress_direction direction, int port)
{
u16 reg; int err;
err = mv88e6xxx_g1_read(chip, MV88E6185_G1_MONITOR_CTL, ®); if (err) return err;
switch (direction) { case MV88E6XXX_EGRESS_DIR_INGRESS:
reg &= ~MV88E6185_G1_MONITOR_CTL_INGRESS_DEST_MASK;
reg |= port <<
__bf_shf(MV88E6185_G1_MONITOR_CTL_INGRESS_DEST_MASK); break; case MV88E6XXX_EGRESS_DIR_EGRESS:
reg &= ~MV88E6185_G1_MONITOR_CTL_EGRESS_DEST_MASK;
reg |= port <<
__bf_shf(MV88E6185_G1_MONITOR_CTL_EGRESS_DEST_MASK); break; default: return -EINVAL;
}
/* Older generations also call this the ARP destination. It has been * generalized in more modern devices such that more than ARP can * egress it
*/ int mv88e6095_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port)
{
u16 reg; int err;
err = mv88e6xxx_g1_read(chip, MV88E6185_G1_MONITOR_CTL, ®); if (err) return err;
reg &= ~MV88E6185_G1_MONITOR_CTL_ARP_DEST_MASK;
reg |= port << __bf_shf(MV88E6185_G1_MONITOR_CTL_ARP_DEST_MASK);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.