#define AR8XXX_CAP_GIGE BIT(0)
+enum {
+ AR8XXX_VER_AR8216 = 0x01,
+ AR8XXX_VER_AR8236 = 0x03,
+ AR8XXX_VER_AR8316 = 0x10,
+ AR8XXX_VER_AR8327 = 0x12,
+};
+
struct ar8xxx_chip {
unsigned long caps;
const struct net_device_ops *ndo_old;
struct net_device_ops ndo;
struct mutex reg_mutex;
- int chip_type;
+ u8 chip_ver;
+ u8 chip_rev;
const struct ar8xxx_chip *chip;
bool initialized;
bool port4_phy;
static inline bool chip_is_ar8216(struct ar8216_priv *priv)
{
- return priv->chip_type == AR8216;
+ return priv->chip_ver == AR8XXX_VER_AR8216;
}
static inline bool chip_is_ar8236(struct ar8216_priv *priv)
{
- return priv->chip_type == AR8236;
+ return priv->chip_ver == AR8XXX_VER_AR8236;
}
static inline bool chip_is_ar8316(struct ar8216_priv *priv)
{
- return priv->chip_type == AR8316;
+ return priv->chip_ver == AR8XXX_VER_AR8316;
}
static inline bool chip_is_ar8327(struct ar8216_priv *priv)
{
- return priv->chip_type == AR8327;
+ return priv->chip_ver == AR8XXX_VER_AR8327;
}
static inline void
mutex_unlock(&bus->mdio_lock);
}
+static void
+ar8216_phy_mmd_write(struct ar8216_priv *priv, int phy_addr, u16 addr, u16 data)
+{
+ struct mii_bus *bus = priv->phy->bus;
+
+ mutex_lock(&bus->mdio_lock);
+ bus->write(bus, phy_addr, MII_ATH_MMD_ADDR, addr);
+ bus->write(bus, phy_addr, MII_ATH_MMD_DATA, data);
+ mutex_unlock(&bus->mdio_lock);
+}
+
static u32
ar8216_rmw(struct ar8216_priv *priv, int reg, u32 mask, u32 val)
{
return t;
}
+static void
+ar8327_phy_fixup(struct ar8216_priv *priv, int phy)
+{
+ switch (priv->chip_rev) {
+ case 1:
+ /* For 100M waveform */
+ ar8216_phy_dbg_write(priv, phy, 0, 0x02ea);
+ /* Turn on Gigabit clock */
+ ar8216_phy_dbg_write(priv, phy, 0x3d, 0x68a0);
+ break;
+
+ case 2:
+ ar8216_phy_mmd_write(priv, phy, 0x7, 0x3c);
+ ar8216_phy_mmd_write(priv, phy, 0x4007, 0x0);
+ /* fallthrough */
+ case 4:
+ ar8216_phy_mmd_write(priv, phy, 0x3, 0x800d);
+ ar8216_phy_mmd_write(priv, phy, 0x4003, 0x803f);
+
+ ar8216_phy_dbg_write(priv, phy, 0x3d, 0x6860);
+ ar8216_phy_dbg_write(priv, phy, 0x5, 0x2c46);
+ ar8216_phy_dbg_write(priv, phy, 0x3c, 0x6000);
+ break;
+ }
+}
+
static int
ar8327_hw_init(struct ar8216_priv *priv)
{
struct ar8327_platform_data *pdata;
+ struct ar8327_led_cfg *led_cfg;
+ struct mii_bus *bus;
+ u32 pos, new_pos;
u32 t;
int i;
t = ar8327_get_pad_cfg(pdata->pad6_cfg);
priv->write(priv, AR8327_REG_PAD6_MODE, t);
- priv->write(priv, AR8327_REG_POWER_ON_STRIP, 0x40000000);
+ pos = priv->read(priv, AR8327_REG_POWER_ON_STRIP);
+ new_pos = pos;
- /* fixup PHYs */
+ led_cfg = pdata->led_cfg;
+ if (led_cfg) {
+ if (led_cfg->open_drain)
+ new_pos |= AR8327_POWER_ON_STRIP_LED_OPEN_EN;
+ else
+ new_pos &= ~AR8327_POWER_ON_STRIP_LED_OPEN_EN;
+
+ priv->write(priv, AR8327_REG_LED_CTRL0, led_cfg->led_ctrl0);
+ priv->write(priv, AR8327_REG_LED_CTRL1, led_cfg->led_ctrl1);
+ priv->write(priv, AR8327_REG_LED_CTRL2, led_cfg->led_ctrl2);
+ priv->write(priv, AR8327_REG_LED_CTRL3, led_cfg->led_ctrl3);
+ }
+
+ if (new_pos != pos) {
+ new_pos |= AR8327_POWER_ON_STRIP_POWER_ON_SEL;
+ priv->write(priv, AR8327_REG_POWER_ON_STRIP, new_pos);
+ }
+
+ bus = priv->phy->bus;
for (i = 0; i < AR8327_NUM_PHYS; i++) {
- /* For 100M waveform */
- ar8216_phy_dbg_write(priv, i, 0, 0x02ea);
+ ar8327_phy_fixup(priv, i);
- /* Turn on Gigabit clock */
- ar8216_phy_dbg_write(priv, i, 0x3d, 0x68a0);
+ /* start aneg on the PHY */
+ mdiobus_write(bus, i, MII_ADVERTISE, ADVERTISE_ALL |
+ ADVERTISE_PAUSE_CAP |
+ ADVERTISE_PAUSE_ASYM);
+ mdiobus_write(bus, i, MII_CTRL1000, ADVERTISE_1000FULL);
+ mdiobus_write(bus, i, MII_BMCR, BMCR_RESET | BMCR_ANENABLE);
}
+ msleep(1000);
+
return 0;
}
u16 id;
int i;
- priv->chip_type = UNKNOWN;
-
val = ar8216_mii_read(priv, AR8216_REG_CTRL);
if (val == ~0)
return -ENODEV;
return -ENODEV;
}
- switch (id) {
- case 0x0101:
- priv->chip_type = AR8216;
+ priv->chip_ver = (id & AR8216_CTRL_VERSION) >> AR8216_CTRL_VERSION_S;
+ priv->chip_rev = (id & AR8216_CTRL_REVISION);
+
+ switch (priv->chip_ver) {
+ case AR8XXX_VER_AR8216:
priv->chip = &ar8216_chip;
break;
- case 0x0301:
- priv->chip_type = AR8236;
+ case AR8XXX_VER_AR8236:
priv->chip = &ar8236_chip;
break;
- case 0x1000:
- case 0x1001:
- priv->chip_type = AR8316;
+ case AR8XXX_VER_AR8316:
priv->chip = &ar8316_chip;
break;
- case 0x1202:
- priv->chip_type = AR8327;
+ case AR8XXX_VER_AR8327:
priv->mii_lo_first = true;
priv->chip = &ar8327_chip;
break;
default:
printk(KERN_DEBUG
"ar8216: Unknown Atheros device [ver=%d, rev=%d, phy_id=%04x%04x]\n",
- (int)(id >> AR8216_CTRL_VERSION_S),
- (int)(id & AR8216_CTRL_REVISION),
+ priv->chip_ver, priv->chip_rev,
mdiobus_read(priv->phy->bus, priv->phy->addr, 2),
mdiobus_read(priv->phy->bus, priv->phy->addr, 3));
return 0;
}
- printk(KERN_INFO "%s: AR%d switch driver attached.\n",
- pdev->attached_dev->name, priv->chip_type);
-
if (ar8xxx_has_gige(priv))
pdev->supported = SUPPORTED_1000baseT_Full;
else
if (ret)
goto err_free_priv;
+ printk(KERN_INFO "%s: %s switch driver attached.\n",
+ pdev->attached_dev->name, swdev->name);
+
priv->init = true;
ret = priv->chip->hw_init(priv);
static int
ar8216_probe(struct phy_device *pdev)
{
- struct ar8216_priv priv;
+ struct ar8216_priv *priv;
+ int ret;
+
+ priv = kzalloc(sizeof(struct ar8216_priv), GFP_KERNEL);
+ if (priv == NULL)
+ return -ENOMEM;
- priv.phy = pdev;
- return ar8216_id_chip(&priv);
+ priv->phy = pdev;
+
+ ret = ar8216_id_chip(priv);
+ kfree(priv);
+
+ return ret;
}
static void