static int mv88e6xxx_g2_trunk_mapping_write(struct mv88e6xxx_chip *chip, int id, u16 map) { const u16 port_mask = BIT(mv88e6xxx_num_ports(chip)) - 1; u16 val = (id << 11) | (map & port_mask); return mv88e6xxx_g2_update(chip, GLOBAL2_TRUNK_MAPPING, val); }
int mv88e6xxx_hwtstamp_setup(struct mv88e6xxx_chip *chip) { const struct mv88e6xxx_ptp_ops *ptp_ops = chip->info->ops->ptp_ops; int err; int i; /* Disable timestamping on all ports. */ for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) { err = mv88e6xxx_hwtstamp_port_setup(chip, i); if (err) return err; } /* Disable PTP globally */ if (ptp_ops->global_disable) { err = ptp_ops->global_disable(chip); if (err) return err; } /* Set the ethertype of L2 PTP messages */ err = mv88e6xxx_ptp_write(chip, MV88E6XXX_PTP_GC_ETYPE, ETH_P_1588); if (err) return err; /* MV88E6XXX_PTP_MSG_TYPE is a mask of PTP message types to * timestamp. This affects all ports that have timestamping enabled, * but the timestamp config is per-port; thus we configure all events * here and only support the HWTSTAMP_FILTER_*_EVENT filter types. */ err = mv88e6xxx_ptp_write(chip, MV88E6XXX_PTP_MSGTYPE, MV88E6XXX_PTP_MSGTYPE_ALL_EVENT); if (err) return err; /* Use ARRIVAL1 for peer delay response messages. */ err = mv88e6xxx_ptp_write(chip, MV88E6XXX_PTP_TS_ARRIVAL_PTR, MV88E6XXX_PTP_MSGTYPE_PDLAY_RES); if (err) return err; /* 88E6341 devices default to timestamping at the PHY, but this has * a hardware issue that results in unreliable timestamps. Force * these devices to timestamp at the MAC. */ if (chip->info->family == MV88E6XXX_FAMILY_6341) { u16 val = MV88E6341_PTP_CFG_UPDATE | MV88E6341_PTP_CFG_MODE_IDX | MV88E6341_PTP_CFG_MODE_TS_AT_MAC; err = mv88e6xxx_ptp_write(chip, MV88E6341_PTP_CFG, val); if (err) return err; } return 0; }
static int mv88e6xxx_g2_trunk_mask_write(struct mv88e6xxx_chip *chip, int num, bool hask, u16 mask) { const u16 port_mask = BIT(mv88e6xxx_num_ports(chip)) - 1; u16 val = (num << 12) | (mask & port_mask); if (hask) val |= GLOBAL2_TRUNK_MASK_HASK; return mv88e6xxx_g2_update(chip, GLOBAL2_TRUNK_MASK, val); }
static int mv88e6xxx_g2_clear_trunk(struct mv88e6xxx_chip *chip) { const u16 port_mask = BIT(mv88e6xxx_num_ports(chip)) - 1; int i, err; /* Clear all eight possible Trunk Mask vectors */ for (i = 0; i < 8; ++i) { err = mv88e6xxx_g2_trunk_mask_write(chip, i, false, port_mask); if (err) return err; } /* Clear all sixteen possible Trunk ID routing vectors */ for (i = 0; i < 16; ++i) { err = mv88e6xxx_g2_trunk_mapping_write(chip, i, 0); if (err) return err; } return 0; }
int mv88e6xxx_port_set_vlan_map(struct mv88e6xxx_chip *chip, int port, u16 map) { const u16 mask = GENMASK(mv88e6xxx_num_ports(chip) - 1, 0); u16 reg; int err; err = mv88e6xxx_port_read(chip, port, PORT_BASE_VLAN, ®); if (err) return err; reg &= ~mask; reg |= map & mask; err = mv88e6xxx_port_write(chip, port, PORT_BASE_VLAN, reg); if (err) return err; netdev_dbg(chip->ds->ports[port].netdev, "VLANTable set to %.3x\n", map); return 0; }
static int mv88e6xxx_g2_clear_irl(struct mv88e6xxx_chip *chip) { int port, err; /* Init all Ingress Rate Limit resources of all ports */ for (port = 0; port < mv88e6xxx_num_ports(chip); ++port) { /* XXX newer chips (like 88E6390) have different 2-bit ops */ err = mv88e6xxx_g2_write(chip, GLOBAL2_IRL_CMD, GLOBAL2_IRL_CMD_OP_INIT_ALL | (port << 8)); if (err) break; /* Wait for the operation to complete */ err = mv88e6xxx_g2_wait(chip, GLOBAL2_IRL_CMD, GLOBAL2_IRL_CMD_BUSY); if (err) break; } return err; }