示例#1
0
文件: b53_mdio.c 项目: Noltari/lede
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;
}
示例#2
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;
}
示例#3
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);
	}
}
示例#4
0
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;
}
示例#5
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);
}
示例#6
0
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);
	}
示例#7
0
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);
}