u32 (*read)(struct ar8xxx_priv *priv, int reg);
void (*write)(struct ar8xxx_priv *priv, int reg, u32 val);
+ u32 (*rmw)(struct ar8xxx_priv *priv, int reg, u32 mask, u32 val);
int (*get_port_link)(unsigned port);
mutex_unlock(&bus->mdio_lock);
}
+static u32
+ar8xxx_mii_rmw(struct ar8xxx_priv *priv, int reg, u32 mask, u32 val)
+{
+ struct mii_bus *bus = priv->mii_bus;
+ u16 r1, r2, page;
+ u16 lo, hi;
+ u32 ret;
+
+ split_addr((u32) reg, &r1, &r2, &page);
+
+ mutex_lock(&bus->mdio_lock);
+
+ bus->write(bus, 0x18, 0, page);
+ usleep_range(1000, 2000); /* wait for the page switch to propagate */
+
+ lo = bus->read(bus, 0x10 | r2, r1);
+ hi = bus->read(bus, 0x10 | r2, r1 + 1);
+
+ ret = hi << 16 | lo;
+ ret &= ~mask;
+ ret |= val;
+
+ lo = ret & 0xffff;
+ hi = (u16) (ret >> 16);
+
+ if (priv->mii_lo_first) {
+ bus->write(bus, 0x10 | r2, r1, lo);
+ bus->write(bus, 0x10 | r2, r1 + 1, hi);
+ } else {
+ bus->write(bus, 0x10 | r2, r1 + 1, hi);
+ bus->write(bus, 0x10 | r2, r1, lo);
+ }
+
+ mutex_unlock(&bus->mdio_lock);
+
+ return ret;
+}
+
+
static void
ar8xxx_phy_dbg_write(struct ar8xxx_priv *priv, int phy_addr,
u16 dbg_addr, u16 dbg_data)
mutex_unlock(&bus->mdio_lock);
}
-static u32
+static inline u32
ar8xxx_rmw(struct ar8xxx_priv *priv, int reg, u32 mask, u32 val)
{
- u32 v;
-
- lockdep_assert_held(&priv->reg_mutex);
-
- v = priv->read(priv, reg);
- v &= ~mask;
- v |= val;
- priv->write(priv, reg, v);
-
- return v;
+ return priv->rmw(priv, reg, mask, val);
}
static inline void
ar8xxx_reg_set(struct ar8xxx_priv *priv, int reg, u32 val)
{
- u32 v;
-
- lockdep_assert_held(&priv->reg_mutex);
-
- v = priv->read(priv, reg);
- v |= val;
- priv->write(priv, reg, v);
+ priv->rmw(priv, reg, 0, val);
}
static int
else
mib_func = AR8216_REG_MIB_FUNC;
- mutex_lock(&priv->reg_mutex);
/* Capture the hardware statistics for all ports */
ar8xxx_rmw(priv, mib_func, AR8216_MIB_FUNC, (op << AR8216_MIB_FUNC_S));
- mutex_unlock(&priv->reg_mutex);
/* Wait for the capturing to complete. */
ret = ar8xxx_reg_wait(priv, mib_func, AR8216_MIB_BUSY, 0, 10);
priv->mii_bus = bus;
priv->read = ar8xxx_mii_read;
priv->write = ar8xxx_mii_write;
+ priv->rmw = ar8xxx_mii_rmw;
}
return priv;