X-Git-Url: http://git.rohieb.name/openwrt.git/blobdiff_plain/166dc561a123b406b0109214e356f93cf0a087a6..6934b97c4e701732bc5b2e33cdcd628ed63ce0db:/target/linux/generic/files/drivers/net/phy/ar8216.c diff --git a/target/linux/generic/files/drivers/net/phy/ar8216.c b/target/linux/generic/files/drivers/net/phy/ar8216.c index 4c5ddc31c..54d57d549 100644 --- a/target/linux/generic/files/drivers/net/phy/ar8216.c +++ b/target/linux/generic/files/drivers/net/phy/ar8216.c @@ -36,6 +36,17 @@ #define AR8X16_MAX_VLANS 128 #define AR8X16_PROBE_RETRIES 10 +struct ar8216_priv; + +struct ar8xxx_chip { + int (*hw_init)(struct ar8216_priv *priv); + void (*init_port)(struct ar8216_priv *priv, int port); + void (*setup_port)(struct ar8216_priv *priv, int port, u32 egress, + u32 ingress, u32 members, u32 pvid); + int (*atu_flush)(struct ar8216_priv *priv); + void (*vtu_flush)(struct ar8216_priv *priv); +}; + struct ar8216_priv { struct switch_dev dev; struct phy_device *phy; @@ -44,7 +55,8 @@ struct ar8216_priv { const struct net_device_ops *ndo_old; struct net_device_ops ndo; struct mutex reg_mutex; - int chip; + int chip_type; + const struct ar8xxx_chip *chip; bool initialized; bool port4_phy; char buf[80]; @@ -471,13 +483,31 @@ ar8216_vtu_op(struct ar8216_priv *priv, u32 op, u32 val) priv->write(priv, AR8216_REG_VTU, op); } +static void +ar8216_vtu_flush(struct ar8216_priv *priv) +{ + ar8216_vtu_op(priv, AR8216_VTU_OP_FLUSH, 0); +} + +static int +ar8216_atu_flush(struct ar8216_priv *priv) +{ + int ret; + + ret = ar8216_wait_bit(priv, AR8216_REG_ATU, AR8216_ATU_ACTIVE, 0); + if (!ret) + priv->write(priv, AR8216_REG_ATU, AR8216_ATU_OP_FLUSH); + + return ret; +} + static void ar8216_setup_port(struct ar8216_priv *priv, int port, u32 egress, u32 ingress, u32 members, u32 pvid) { u32 header; - if (priv->vlan && port == AR8216_PORT_CPU && priv->chip == AR8216) + if (priv->vlan && port == AR8216_PORT_CPU && priv->chip_type == AR8216) header = AR8216_PORT_CTRL_HEADER; else header = 0; @@ -530,7 +560,7 @@ ar8216_hw_apply(struct switch_dev *dev) mutex_lock(&priv->reg_mutex); /* flush all vlan translation unit entries */ - ar8216_vtu_op(priv, AR8216_VTU_OP_FLUSH, 0); + priv->chip->vtu_flush(priv); memset(portmask, 0, sizeof(portmask)); if (!priv->init) { @@ -583,12 +613,8 @@ ar8216_hw_apply(struct switch_dev *dev) ingress = AR8216_IN_PORT_ONLY; } - if (priv->chip == AR8236) - ar8236_setup_port(priv, i, egress, ingress, portmask[i], - pvid); - else - ar8216_setup_port(priv, i, egress, ingress, portmask[i], - pvid); + priv->chip->setup_port(priv, i, egress, ingress, portmask[i], + pvid); } mutex_unlock(&priv->reg_mutex); return 0; @@ -686,7 +712,7 @@ out: static void ar8216_init_globals(struct ar8216_priv *priv) { - switch (priv->chip) { + switch (priv->chip_type) { case AR8216: /* standard atheros magic */ priv->write(priv, 0x38, 0xc000050e); @@ -723,12 +749,12 @@ ar8216_init_port(struct ar8216_priv *priv, int port) if (port == AR8216_PORT_CPU) { priv->write(priv, AR8216_REG_PORT_STATUS(port), AR8216_PORT_STATUS_LINK_UP | - ((priv->chip == AR8316) ? + ((priv->chip_type == AR8316) ? AR8216_PORT_SPEED_1000M : AR8216_PORT_SPEED_100M) | AR8216_PORT_STATUS_TXMAC | AR8216_PORT_STATUS_RXMAC | - ((priv->chip == AR8316) ? AR8216_PORT_STATUS_RXFLOW : 0) | - ((priv->chip == AR8316) ? AR8216_PORT_STATUS_TXFLOW : 0) | + ((priv->chip_type == AR8316) ? AR8216_PORT_STATUS_RXFLOW : 0) | + ((priv->chip_type == AR8316) ? AR8216_PORT_STATUS_TXFLOW : 0) | AR8216_PORT_STATUS_DUPLEX); } else { priv->write(priv, AR8216_REG_PORT_STATUS(port), @@ -736,6 +762,30 @@ ar8216_init_port(struct ar8216_priv *priv, int port) } } +static const struct ar8xxx_chip ar8216_chip = { + .hw_init = ar8216_hw_init, + .init_port = ar8216_init_port, + .setup_port = ar8216_setup_port, + .atu_flush = ar8216_atu_flush, + .vtu_flush = ar8216_vtu_flush, +}; + +static const struct ar8xxx_chip ar8236_chip = { + .hw_init = ar8236_hw_init, + .init_port = ar8216_init_port, + .setup_port = ar8236_setup_port, + .atu_flush = ar8216_atu_flush, + .vtu_flush = ar8216_vtu_flush, +}; + +static const struct ar8xxx_chip ar8316_chip = { + .hw_init = ar8316_hw_init, + .init_port = ar8216_init_port, + .setup_port = ar8216_setup_port, + .atu_flush = ar8216_atu_flush, + .vtu_flush = ar8216_vtu_flush, +}; + static int ar8216_reset_switch(struct switch_dev *dev) { @@ -751,7 +801,7 @@ ar8216_reset_switch(struct switch_dev *dev) /* Configure all ports */ for (i = 0; i < AR8216_NUM_PORTS; i++) - ar8216_init_port(priv, i); + priv->chip->init_port(priv, i); ar8216_init_globals(priv); mutex_unlock(&priv->reg_mutex); @@ -788,7 +838,7 @@ ar8216_id_chip(struct ar8216_priv *priv) u16 id; int i; - priv->chip = UNKNOWN; + priv->chip_type = UNKNOWN; val = ar8216_mii_read(priv, AR8216_REG_CTRL); if (val == ~0) @@ -809,14 +859,17 @@ ar8216_id_chip(struct ar8216_priv *priv) switch (id) { case 0x0101: - priv->chip = AR8216; + priv->chip_type = AR8216; + priv->chip = &ar8216_chip; break; case 0x0301: - priv->chip = AR8236; + priv->chip_type = AR8236; + priv->chip = &ar8236_chip; break; case 0x1000: case 0x1001: - priv->chip = AR8316; + priv->chip_type = AR8316; + priv->chip = &ar8316_chip; break; default: printk(KERN_DEBUG @@ -853,7 +906,7 @@ ar8216_config_init(struct phy_device *pdev) goto err_free_priv; if (pdev->addr != 0) { - if (priv->chip == AR8316) { + if (priv->chip_type == AR8316) { pdev->supported |= SUPPORTED_1000baseT_Full; pdev->advertising |= ADVERTISED_1000baseT_Full; @@ -887,9 +940,9 @@ ar8216_config_init(struct phy_device *pdev) } printk(KERN_INFO "%s: AR%d switch driver attached.\n", - pdev->attached_dev->name, priv->chip); + pdev->attached_dev->name, priv->chip_type); - pdev->supported = priv->chip == AR8316 ? + pdev->supported = priv->chip_type == AR8316 ? SUPPORTED_1000baseT_Full : SUPPORTED_100baseT_Full; pdev->advertising = pdev->supported; @@ -904,7 +957,7 @@ ar8216_config_init(struct phy_device *pdev) swdev->ops = &ar8216_sw_ops; swdev->ports = AR8216_NUM_PORTS; - if (priv->chip == AR8316) { + if (priv->chip_type == AR8316) { swdev->name = "Atheros AR8316"; swdev->vlans = AR8X16_MAX_VLANS; @@ -912,7 +965,7 @@ ar8216_config_init(struct phy_device *pdev) /* port 5 connected to the other mac, therefore unusable */ swdev->ports = (AR8216_NUM_PORTS - 1); } - } else if (priv->chip == AR8236) { + } else if (priv->chip_type == AR8236) { swdev->name = "Atheros AR8236"; swdev->vlans = AR8216_NUM_VLANS; swdev->ports = AR8216_NUM_PORTS; @@ -927,14 +980,7 @@ ar8216_config_init(struct phy_device *pdev) priv->init = true; - ret = 0; - if (priv->chip == AR8216) - ret = ar8216_hw_init(priv); - else if (priv->chip == AR8236) - ret = ar8236_hw_init(priv); - else if (priv->chip == AR8316) - ret = ar8316_hw_init(priv); - + ret = priv->chip->hw_init(priv); if (ret) goto err_free_priv; @@ -945,7 +991,7 @@ ar8216_config_init(struct phy_device *pdev) dev->phy_ptr = priv; /* VID fixup only needed on ar8216 */ - if (pdev->addr == 0 && priv->chip == AR8216) { + if (pdev->addr == 0 && priv->chip_type == AR8216) { pdev->pkt_align = 2; pdev->netif_receive_skb = ar8216_netif_receive_skb; pdev->netif_rx = ar8216_netif_rx; @@ -996,9 +1042,7 @@ ar8216_read_status(struct phy_device *phydev) /* flush the address translation unit */ mutex_lock(&priv->reg_mutex); - ret = ar8216_wait_bit(priv, AR8216_REG_ATU, AR8216_ATU_ACTIVE, 0); - if (!ret) - priv->write(priv, AR8216_REG_ATU, AR8216_ATU_OP_FLUSH); + ret = priv->chip->atu_flush(priv); mutex_unlock(&priv->reg_mutex); phydev->state = PHY_RUNNING;