Commit c766e077 authored by Christian Marangi's avatar Christian Marangi Committed by David S. Miller

net: dsa: qca8k: convert to regmap read/write API

Convert qca8k to regmap read/write bulk API. The mgmt eth can write up
to 32 bytes of data at times. Currently we use a custom function to do
it but regmap now supports declaration of read/write bulk even without a
bus.

Drop the custom function and rework the regmap function to this new
implementation.

Rework the qca8k_fdb_read/write function to use the new
regmap_bulk_read/write as the old qca8k_bulk_read/write are now dropped.

Cc: Mark Brown <broonie@kernel.org>
Signed-off-by: default avatarChristian Marangi <ansuelsmth@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e03cea60
...@@ -425,16 +425,12 @@ qca8k_regmap_update_bits_eth(struct qca8k_priv *priv, u32 reg, u32 mask, u32 wri ...@@ -425,16 +425,12 @@ qca8k_regmap_update_bits_eth(struct qca8k_priv *priv, u32 reg, u32 mask, u32 wri
} }
static int static int
qca8k_regmap_read(void *ctx, uint32_t reg, uint32_t *val) qca8k_read_mii(struct qca8k_priv *priv, uint32_t reg, uint32_t *val)
{ {
struct qca8k_priv *priv = (struct qca8k_priv *)ctx;
struct mii_bus *bus = priv->bus; struct mii_bus *bus = priv->bus;
u16 r1, r2, page; u16 r1, r2, page;
int ret; int ret;
if (!qca8k_read_eth(priv, reg, val, sizeof(*val)))
return 0;
qca8k_split_addr(reg, &r1, &r2, &page); qca8k_split_addr(reg, &r1, &r2, &page);
mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
...@@ -451,16 +447,12 @@ qca8k_regmap_read(void *ctx, uint32_t reg, uint32_t *val) ...@@ -451,16 +447,12 @@ qca8k_regmap_read(void *ctx, uint32_t reg, uint32_t *val)
} }
static int static int
qca8k_regmap_write(void *ctx, uint32_t reg, uint32_t val) qca8k_write_mii(struct qca8k_priv *priv, uint32_t reg, uint32_t val)
{ {
struct qca8k_priv *priv = (struct qca8k_priv *)ctx;
struct mii_bus *bus = priv->bus; struct mii_bus *bus = priv->bus;
u16 r1, r2, page; u16 r1, r2, page;
int ret; int ret;
if (!qca8k_write_eth(priv, reg, &val, sizeof(val)))
return 0;
qca8k_split_addr(reg, &r1, &r2, &page); qca8k_split_addr(reg, &r1, &r2, &page);
mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
...@@ -477,17 +469,14 @@ qca8k_regmap_write(void *ctx, uint32_t reg, uint32_t val) ...@@ -477,17 +469,14 @@ qca8k_regmap_write(void *ctx, uint32_t reg, uint32_t val)
} }
static int static int
qca8k_regmap_update_bits(void *ctx, uint32_t reg, uint32_t mask, uint32_t write_val) qca8k_regmap_update_bits_mii(struct qca8k_priv *priv, uint32_t reg,
uint32_t mask, uint32_t write_val)
{ {
struct qca8k_priv *priv = (struct qca8k_priv *)ctx;
struct mii_bus *bus = priv->bus; struct mii_bus *bus = priv->bus;
u16 r1, r2, page; u16 r1, r2, page;
u32 val; u32 val;
int ret; int ret;
if (!qca8k_regmap_update_bits_eth(priv, reg, mask, write_val))
return 0;
qca8k_split_addr(reg, &r1, &r2, &page); qca8k_split_addr(reg, &r1, &r2, &page);
mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
...@@ -510,17 +499,84 @@ qca8k_regmap_update_bits(void *ctx, uint32_t reg, uint32_t mask, uint32_t write_ ...@@ -510,17 +499,84 @@ qca8k_regmap_update_bits(void *ctx, uint32_t reg, uint32_t mask, uint32_t write_
return ret; return ret;
} }
static int
qca8k_bulk_read(void *ctx, const void *reg_buf, size_t reg_len,
void *val_buf, size_t val_len)
{
int i, count = val_len / sizeof(u32), ret;
u32 reg = *(u32 *)reg_buf & U16_MAX;
struct qca8k_priv *priv = ctx;
if (priv->mgmt_master &&
!qca8k_read_eth(priv, reg, val_buf, val_len))
return 0;
/* loop count times and increment reg of 4 */
for (i = 0; i < count; i++, reg += sizeof(u32)) {
ret = qca8k_read_mii(priv, reg, val_buf + i);
if (ret < 0)
return ret;
}
return 0;
}
static int
qca8k_bulk_gather_write(void *ctx, const void *reg_buf, size_t reg_len,
const void *val_buf, size_t val_len)
{
int i, count = val_len / sizeof(u32), ret;
u32 reg = *(u32 *)reg_buf & U16_MAX;
struct qca8k_priv *priv = ctx;
u32 *val = (u32 *)val_buf;
if (priv->mgmt_master &&
!qca8k_write_eth(priv, reg, val, val_len))
return 0;
/* loop count times, increment reg of 4 and increment val ptr to
* the next value
*/
for (i = 0; i < count; i++, reg += sizeof(u32), val++) {
ret = qca8k_write_mii(priv, reg, *val);
if (ret < 0)
return ret;
}
return 0;
}
static int
qca8k_bulk_write(void *ctx, const void *data, size_t bytes)
{
return qca8k_bulk_gather_write(ctx, data, sizeof(u16), data + sizeof(u16),
bytes - sizeof(u16));
}
static int
qca8k_regmap_update_bits(void *ctx, uint32_t reg, uint32_t mask, uint32_t write_val)
{
struct qca8k_priv *priv = ctx;
if (!qca8k_regmap_update_bits_eth(priv, reg, mask, write_val))
return 0;
return qca8k_regmap_update_bits_mii(priv, reg, mask, write_val);
}
static struct regmap_config qca8k_regmap_config = { static struct regmap_config qca8k_regmap_config = {
.reg_bits = 16, .reg_bits = 16,
.val_bits = 32, .val_bits = 32,
.reg_stride = 4, .reg_stride = 4,
.max_register = 0x16ac, /* end MIB - Port6 range */ .max_register = 0x16ac, /* end MIB - Port6 range */
.reg_read = qca8k_regmap_read, .read = qca8k_bulk_read,
.reg_write = qca8k_regmap_write, .write = qca8k_bulk_write,
.reg_update_bits = qca8k_regmap_update_bits, .reg_update_bits = qca8k_regmap_update_bits,
.rd_table = &qca8k_readable_table, .rd_table = &qca8k_readable_table,
.disable_locking = true, /* Locking is handled by qca8k read/write */ .disable_locking = true, /* Locking is handled by qca8k read/write */
.cache_type = REGCACHE_NONE, /* Explicitly disable CACHE */ .cache_type = REGCACHE_NONE, /* Explicitly disable CACHE */
.max_raw_read = 32, /* mgmt eth can read/write up to 8 registers at time */
.max_raw_write = 32,
}; };
static int static int
...@@ -2089,8 +2145,6 @@ static SIMPLE_DEV_PM_OPS(qca8k_pm_ops, ...@@ -2089,8 +2145,6 @@ static SIMPLE_DEV_PM_OPS(qca8k_pm_ops,
static const struct qca8k_info_ops qca8xxx_ops = { static const struct qca8k_info_ops qca8xxx_ops = {
.autocast_mib = qca8k_get_ethtool_stats_eth, .autocast_mib = qca8k_get_ethtool_stats_eth,
.read_eth = qca8k_read_eth,
.write_eth = qca8k_write_eth,
}; };
static const struct qca8k_match_data qca8327 = { static const struct qca8k_match_data qca8327 = {
......
...@@ -101,45 +101,6 @@ const struct regmap_access_table qca8k_readable_table = { ...@@ -101,45 +101,6 @@ const struct regmap_access_table qca8k_readable_table = {
.n_yes_ranges = ARRAY_SIZE(qca8k_readable_ranges), .n_yes_ranges = ARRAY_SIZE(qca8k_readable_ranges),
}; };
/* TODO: remove these extra ops when we can support regmap bulk read/write */
static int qca8k_bulk_read(struct qca8k_priv *priv, u32 reg, u32 *val, int len)
{
int i, count = len / sizeof(u32), ret;
if (priv->mgmt_master && priv->info->ops->read_eth &&
!priv->info->ops->read_eth(priv, reg, val, len))
return 0;
for (i = 0; i < count; i++) {
ret = regmap_read(priv->regmap, reg + (i * 4), val + i);
if (ret < 0)
return ret;
}
return 0;
}
/* TODO: remove these extra ops when we can support regmap bulk read/write */
static int qca8k_bulk_write(struct qca8k_priv *priv, u32 reg, u32 *val, int len)
{
int i, count = len / sizeof(u32), ret;
u32 tmp;
if (priv->mgmt_master && priv->info->ops->write_eth &&
!priv->info->ops->write_eth(priv, reg, val, len))
return 0;
for (i = 0; i < count; i++) {
tmp = val[i];
ret = regmap_write(priv->regmap, reg + (i * 4), tmp);
if (ret < 0)
return ret;
}
return 0;
}
static int qca8k_busy_wait(struct qca8k_priv *priv, u32 reg, u32 mask) static int qca8k_busy_wait(struct qca8k_priv *priv, u32 reg, u32 mask)
{ {
u32 val; u32 val;
...@@ -154,8 +115,8 @@ static int qca8k_fdb_read(struct qca8k_priv *priv, struct qca8k_fdb *fdb) ...@@ -154,8 +115,8 @@ static int qca8k_fdb_read(struct qca8k_priv *priv, struct qca8k_fdb *fdb)
int ret; int ret;
/* load the ARL table into an array */ /* load the ARL table into an array */
ret = qca8k_bulk_read(priv, QCA8K_REG_ATU_DATA0, reg, ret = regmap_bulk_read(priv->regmap, QCA8K_REG_ATU_DATA0, reg,
QCA8K_ATU_TABLE_SIZE * sizeof(u32)); QCA8K_ATU_TABLE_SIZE);
if (ret) if (ret)
return ret; return ret;
...@@ -196,8 +157,8 @@ static void qca8k_fdb_write(struct qca8k_priv *priv, u16 vid, u8 port_mask, ...@@ -196,8 +157,8 @@ static void qca8k_fdb_write(struct qca8k_priv *priv, u16 vid, u8 port_mask,
reg[0] |= FIELD_PREP(QCA8K_ATU_ADDR5_MASK, mac[5]); reg[0] |= FIELD_PREP(QCA8K_ATU_ADDR5_MASK, mac[5]);
/* load the array into the ARL table */ /* load the array into the ARL table */
qca8k_bulk_write(priv, QCA8K_REG_ATU_DATA0, reg, regmap_bulk_write(priv->regmap, QCA8K_REG_ATU_DATA0, reg,
QCA8K_ATU_TABLE_SIZE * sizeof(u32)); QCA8K_ATU_TABLE_SIZE);
} }
static int qca8k_fdb_access(struct qca8k_priv *priv, enum qca8k_fdb_cmd cmd, static int qca8k_fdb_access(struct qca8k_priv *priv, enum qca8k_fdb_cmd cmd,
......
...@@ -330,9 +330,6 @@ struct qca8k_priv; ...@@ -330,9 +330,6 @@ struct qca8k_priv;
struct qca8k_info_ops { struct qca8k_info_ops {
int (*autocast_mib)(struct dsa_switch *ds, int port, u64 *data); int (*autocast_mib)(struct dsa_switch *ds, int port, u64 *data);
/* TODO: remove these extra ops when we can support regmap bulk read/write */
int (*read_eth)(struct qca8k_priv *priv, u32 reg, u32 *val, int len);
int (*write_eth)(struct qca8k_priv *priv, u32 reg, u32 *val, int len);
}; };
struct qca8k_match_data { struct qca8k_match_data {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment