static int b53_phy_probe(struct phy_device *phydev) { struct b53_device *dev; int ret; /* allow the generic phy driver to take over */ if (phydev->mdio.addr != B53_PSEUDO_PHY && phydev->mdio.addr != 0) return -ENODEV; dev = b53_switch_alloc(&phydev->mdio.dev, &b53_mdio_ops, phydev->mdio.bus); if (!dev) return -ENOMEM; dev->current_page = 0xff; dev->priv = phydev->mdio.bus; dev->ops = &b53_mdio_ops; dev->pdata = NULL; mutex_init(&dev->reg_mutex); ret = b53_switch_detect(dev); if (ret) return ret; #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) linkmode_zero(phydev->supported); if (is5325(dev) || is5365(dev)) linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, phydev->supported); else linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, phydev->supported); linkmode_copy(phydev->advertising, phydev->supported); #else if (is5325(dev) || is5365(dev)) phydev->supported = SUPPORTED_100baseT_Full; else phydev->supported = SUPPORTED_1000baseT_Full; phydev->advertising = phydev->supported; #endif ret = b53_switch_register(dev); if (ret) { dev_err(dev->dev, "failed to register switch: %i\n", ret); return ret; } phydev->priv = dev; return 0; }
static int b53_phy_probe(struct phy_device *phydev) { struct b53_device dev; int ret; /* allow the generic phy driver to take over */ if (phydev->addr != B53_PSEUDO_PHY && phydev->addr != 0) return -ENODEV; dev.current_page = 0xff; dev.priv = phydev->bus; dev.ops = &b53_mdio_ops; dev.pdata = NULL; mutex_init(&dev.reg_mutex); ret = b53_switch_detect(&dev); if (ret) return ret; if (is5325(&dev) || is5365(&dev)) phydev->supported = SUPPORTED_100baseT_Full; else phydev->supported = SUPPORTED_1000baseT_Full; phydev->advertising = phydev->supported; return 0; }
static void b53_set_vlan_entry(struct b53_device *dev, u16 vid, u16 members, u16 untag) { if (is5325(dev)) { u32 entry = 0; if (members) entry = (untag << VA_UNTAG_S) | members | VA_VALID_25; b53_write32(dev, B53_VLAN_PAGE, B53_VLAN_WRITE_25, entry); b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_TABLE_ACCESS_25, vid | VTA_RW_STATE_WR | VTA_RW_OP_EN); } else if (is5365(dev)) { u16 entry = 0; if (members) entry = (untag << VA_UNTAG_S) | members | VA_VALID_65; b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_WRITE_65, entry); b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_TABLE_ACCESS_65, vid | VTA_RW_STATE_WR | VTA_RW_OP_EN); } else { b53_write16(dev, B53_ARLIO_PAGE, dev->vta_regs[1], vid); b53_write32(dev, B53_ARLIO_PAGE, dev->vta_regs[2], (untag << VTE_UNTAG_S) | members); b53_do_vlan_op(dev, VTA_CMD_WRITE); } }
static int b53_phy_read_status(struct phy_device *phydev) { struct b53_device *priv = phydev->priv; if (is5325(priv) || is5365(priv)) phydev->speed = 100; else phydev->speed = 1000; phydev->duplex = DUPLEX_FULL; phydev->link = 1; phydev->state = PHY_RUNNING; netif_carrier_on(phydev->attached_dev); phydev->adjust_link(phydev->attached_dev); return 0; }
static int b53_set_jumbo(struct b53_device *dev, int enable, int allow_10_100) { u32 port_mask = 0; u16 max_size = JMS_MIN_SIZE; if (is5325(dev) || is5365(dev)) return -EINVAL; if (enable) { port_mask = dev->enabled_ports; max_size = JMS_MAX_SIZE; if (allow_10_100) port_mask |= JPM_10_100_JUMBO_EN; } b53_write32(dev, B53_JUMBO_PAGE, dev->jumbo_pm_reg, port_mask); return b53_write16(dev, B53_JUMBO_PAGE, dev->jumbo_size_reg, max_size); }
static void b53_enable_ports(struct b53_device *dev) { unsigned i; b53_for_each_port(dev, i) { u8 port_ctrl; u16 pvlan_mask; /* * prevent leaking packets between wan and lan in unmanaged * mode through port vlans. */ if (dev->enable_vlan || is_cpu_port(dev, i)) pvlan_mask = 0x1ff; else if (is531x5(dev) || is5301x(dev)) /* BCM53115 may use a different port as cpu port */ pvlan_mask = BIT(dev->sw_dev.cpu_port); else pvlan_mask = BIT(B53_CPU_PORT); /* BCM5325 CPU port is at 8 */ if ((is5325(dev) || is5365(dev)) && i == B53_CPU_PORT_25) i = B53_CPU_PORT; if (dev->chip_id == BCM5398_DEVICE_ID && (i == 6 || i == 7)) /* disable unused ports 6 & 7 */ port_ctrl = PORT_CTRL_RX_DISABLE | PORT_CTRL_TX_DISABLE; else if (i == B53_CPU_PORT) port_ctrl = PORT_CTRL_RX_BCST_EN | PORT_CTRL_RX_MCST_EN | PORT_CTRL_RX_UCST_EN; else port_ctrl = 0; b53_write16(dev, B53_PVLAN_PAGE, B53_PVLAN_PORT_MASK(i), pvlan_mask); /* port state is handled by bcm63xx_enet driver */ if (!is63xx(dev) && !(is5301x(dev) && i == 6)) b53_write8(dev, B53_CTRL_PAGE, B53_PORT_CTRL(i), port_ctrl); }
static void b53_enable_vlan(struct b53_device *dev, int enable) { u8 mgmt, vc0, vc1, vc4 = 0, vc5; b53_read8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, &mgmt); b53_read8(dev, B53_VLAN_PAGE, B53_VLAN_CTRL0, &vc0); b53_read8(dev, B53_VLAN_PAGE, B53_VLAN_CTRL1, &vc1); if (is5325(dev) || is5365(dev)) { b53_read8(dev, B53_VLAN_PAGE, B53_VLAN_CTRL4_25, &vc4); b53_read8(dev, B53_VLAN_PAGE, B53_VLAN_CTRL5_25, &vc5); } else if (is63xx(dev)) { b53_read8(dev, B53_VLAN_PAGE, B53_VLAN_CTRL4_63XX, &vc4); b53_read8(dev, B53_VLAN_PAGE, B53_VLAN_CTRL5_63XX, &vc5); } else { b53_read8(dev, B53_VLAN_PAGE, B53_VLAN_CTRL4, &vc4); b53_read8(dev, B53_VLAN_PAGE, B53_VLAN_CTRL5, &vc5); } mgmt &= ~SM_SW_FWD_MODE; if (enable) { vc0 |= VC0_VLAN_EN | VC0_VID_CHK_EN | VC0_VID_HASH_VID; vc1 |= VC1_RX_MCST_UNTAG_EN | VC1_RX_MCST_FWD_EN; vc4 &= ~VC4_ING_VID_CHECK_MASK; vc4 |= VC4_ING_VID_VIO_DROP << VC4_ING_VID_CHECK_S; vc5 |= VC5_DROP_VTABLE_MISS; if (is5325(dev)) vc0 &= ~VC0_RESERVED_1; if (is5325(dev) || is5365(dev)) vc1 |= VC1_RX_MCST_TAG_EN; if (!is5325(dev) && !is5365(dev)) { if (dev->allow_vid_4095) vc5 |= VC5_VID_FFF_EN; else vc5 &= ~VC5_VID_FFF_EN; } } else { vc0 &= ~(VC0_VLAN_EN | VC0_VID_CHK_EN | VC0_VID_HASH_VID); vc1 &= ~(VC1_RX_MCST_UNTAG_EN | VC1_RX_MCST_FWD_EN); vc4 &= ~VC4_ING_VID_CHECK_MASK; vc5 &= ~VC5_DROP_VTABLE_MISS; if (is5325(dev) || is5365(dev)) vc4 |= VC4_ING_VID_VIO_FWD << VC4_ING_VID_CHECK_S; else vc4 |= VC4_ING_VID_VIO_TO_IMP << VC4_ING_VID_CHECK_S; if (is5325(dev) || is5365(dev)) vc1 &= ~VC1_RX_MCST_TAG_EN; if (!is5325(dev) && !is5365(dev)) vc5 &= ~VC5_VID_FFF_EN; } b53_write8(dev, B53_VLAN_PAGE, B53_VLAN_CTRL0, vc0); b53_write8(dev, B53_VLAN_PAGE, B53_VLAN_CTRL1, vc1); if (is5325(dev) || is5365(dev)) { /* enable the high 8 bit vid check on 5325 */ if (is5325(dev) && enable) b53_write8(dev, B53_VLAN_PAGE, B53_VLAN_CTRL3, VC3_HIGH_8BIT_EN); else b53_write8(dev, B53_VLAN_PAGE, B53_VLAN_CTRL3, 0); b53_write8(dev, B53_VLAN_PAGE, B53_VLAN_CTRL4_25, vc4); b53_write8(dev, B53_VLAN_PAGE, B53_VLAN_CTRL5_25, vc5); } else if (is63xx(dev)) { b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_CTRL3_63XX, 0); b53_write8(dev, B53_VLAN_PAGE, B53_VLAN_CTRL4_63XX, vc4); b53_write8(dev, B53_VLAN_PAGE, B53_VLAN_CTRL5_63XX, vc5); } else { b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_CTRL3, 0); b53_write8(dev, B53_VLAN_PAGE, B53_VLAN_CTRL4, vc4); b53_write8(dev, B53_VLAN_PAGE, B53_VLAN_CTRL5, vc5); } b53_write8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, mgmt); }