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); }
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); }
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; }