Example #1
0
static int ag71xx_mdio_read(struct mii_bus *bus, int addr, int reg)
{
	struct ag71xx_mdio *am = bus->priv;

	if (am->pdata->is_ar7240)
		return ar7240sw_phy_read(bus, addr, reg);
	else
		return ag71xx_mdio_mii_read(am, addr, reg);
}
Example #2
0
static void link_function(struct work_struct *work) {
	struct ag71xx *ag = container_of(work, struct ag71xx, link_work.work);
	struct ar7240sw *as = ag->phy_priv;
	unsigned long flags;
	u8 mask;
	int i;
	int status = 0, link_up_count = 0;

	mask = ~as->swdata->phy_poll_mask;
	for (i = 0; i < AR7240_NUM_PHYS; i++) {
		int link;

		if (!(mask & BIT(i)))
			continue;

		link = ar7240sw_phy_read(ag->mii_bus, i, MII_BMSR);
		if (link & BMSR_LSTATUS) {
			status = 1;
			link_up_count++;
		}
	}

	if (link_up_count != 0 && as->num_ports_linkup != link_up_count) {

		/* Set flowcontrol threshold based on linkup count */

		if (link_up_count == 1)
			ar7240sw_reg_write(as->mii_bus, 0x34, 0x16602090);
		else if (link_up_count == 2)
			ar7240sw_reg_write(as->mii_bus, 0x34, 0x90bcc0ff);
		else if (link_up_count > 2)
			ar7240sw_reg_write(as->mii_bus, 0x34, 0xb0c0c0ff);

		as->num_ports_linkup = link_up_count;
	}

	spin_lock_irqsave(&ag->lock, flags);
	if (status != ag->link) {
		ag->link = status;
		ag71xx_link_adjust(ag);
	}
	spin_unlock_irqrestore(&ag->lock, flags);

	schedule_delayed_work(&ag->link_work, HZ / 2);
}
Example #3
0
static struct ar7240sw *ar7240_probe(struct ag71xx *ag)
{
	struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag);
	struct mii_bus *mii = ag->mii_bus;
	struct ar7240sw *as;
	struct switch_dev *swdev;
	u32 ctrl;
	u16 phy_id1;
	u16 phy_id2;
	int i;

	phy_id1 = ar7240sw_phy_read(mii, 0, MII_PHYSID1);
	phy_id2 = ar7240sw_phy_read(mii, 0, MII_PHYSID2);
	if ((phy_id1 != AR7240_PHY_ID1 || phy_id2 != AR7240_PHY_ID2) &&
	    (phy_id1 != AR934X_PHY_ID1 || phy_id2 != AR934X_PHY_ID2)) {
		pr_err("%s: unknown phy id '%04x:%04x'\n",
		       ag->dev->name, phy_id1, phy_id2);
		return NULL;
	}

	as = kzalloc(sizeof(*as), GFP_KERNEL);
	if (!as)
		return NULL;

	as->mii_bus = mii;
	as->swdata = pdata->switch_data;

	swdev = &as->swdev;

	ctrl = ar7240sw_reg_read(mii, AR7240_REG_MASK_CTRL);
	as->ver = (ctrl >> AR7240_MASK_CTRL_VERSION_S) &
		  AR7240_MASK_CTRL_VERSION_M;

	if (sw_is_ar7240(as)) {
		swdev->name = "AR7240/AR9330 built-in switch";
		swdev->ports = AR7240_NUM_PORTS - 1;
	} else if (sw_is_ar934x(as)) {
		swdev->name = "AR934X built-in switch";

		if (pdata->phy_if_mode == PHY_INTERFACE_MODE_GMII) {
			ar7240sw_reg_set(mii, AR934X_REG_OPER_MODE0,
					 AR934X_OPER_MODE0_MAC_GMII_EN);
		} else if (pdata->phy_if_mode == PHY_INTERFACE_MODE_MII) {
			ar7240sw_reg_set(mii, AR934X_REG_OPER_MODE0,
					 AR934X_OPER_MODE0_PHY_MII_EN);
		} else {
			pr_err("%s: invalid PHY interface mode\n",
			       ag->dev->name);
			goto err_free;
		}

		if (as->swdata->phy4_mii_en) {
			ar7240sw_reg_set(mii, AR934X_REG_OPER_MODE1,
					 AR934X_REG_OPER_MODE1_PHY4_MII_EN);
			swdev->ports = AR7240_NUM_PORTS - 1;
		} else {
			swdev->ports = AR7240_NUM_PORTS;
		}
	} else {
		pr_err("%s: unsupported chip, ctrl=%08x\n",
			ag->dev->name, ctrl);
		goto err_free;
	}

	swdev->cpu_port = AR7240_PORT_CPU;
	swdev->vlans = AR7240_MAX_VLANS;
	swdev->ops = &ar7240_ops;

	if (register_switch(&as->swdev, ag->dev) < 0)
		goto err_free;

	pr_info("%s: Found an %s\n", ag->dev->name, swdev->name);

	/* initialize defaults */
	for (i = 0; i < AR7240_MAX_VLANS; i++)
		as->vlan_id[i] = i;

	as->vlan_table[0] = ar7240sw_port_mask_all(as);

	return as;

err_free:
	kfree(as);
	return NULL;
}