Commit 8b5f3f29 authored by Ansuel Smith's avatar Ansuel Smith Committed by David S. Miller

net: dsa: qca8k: initial conversion to regmap helper

Convert any qca8k set/clear/pool to regmap helper and add
missing config to regmap_config struct.
Read/write/rmw operation are reworked to use the regmap helper
internally to keep the delta of this patch low. These additional
function will then be dropped when the code split will be proposed.

Ipq40xx SoC have the internal switch based on the qca8k regmap but use
mmio for read/write/rmw operation instead of mdio.
In preparation for the support of this internal switch, convert the
driver to regmap API to later split the driver to common and specific
code. The overhead introduced by the use of regamp API is marginal as the
internal mdio will bypass it by using its direct access and regmap will be
used only by configuration functions or fdb access.
Signed-off-by: default avatarAnsuel Smith <ansuelsmth@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 36b8af12
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <linux/phy.h> #include <linux/phy.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/bitfield.h> #include <linux/bitfield.h>
#include <linux/regmap.h>
#include <net/dsa.h> #include <net/dsa.h>
#include <linux/of_net.h> #include <linux/of_net.h>
#include <linux/of_mdio.h> #include <linux/of_mdio.h>
...@@ -152,6 +153,25 @@ qca8k_set_page(struct mii_bus *bus, u16 page) ...@@ -152,6 +153,25 @@ qca8k_set_page(struct mii_bus *bus, u16 page)
static int static int
qca8k_read(struct qca8k_priv *priv, u32 reg, u32 *val) qca8k_read(struct qca8k_priv *priv, u32 reg, u32 *val)
{ {
return regmap_read(priv->regmap, reg, val);
}
static int
qca8k_write(struct qca8k_priv *priv, u32 reg, u32 val)
{
return regmap_write(priv->regmap, reg, val);
}
static int
qca8k_rmw(struct qca8k_priv *priv, u32 reg, u32 mask, u32 write_val)
{
return regmap_update_bits(priv->regmap, reg, mask, write_val);
}
static int
qca8k_regmap_read(void *ctx, 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;
...@@ -172,8 +192,9 @@ qca8k_read(struct qca8k_priv *priv, u32 reg, u32 *val) ...@@ -172,8 +192,9 @@ qca8k_read(struct qca8k_priv *priv, u32 reg, u32 *val)
} }
static int static int
qca8k_write(struct qca8k_priv *priv, u32 reg, u32 val) qca8k_regmap_write(void *ctx, 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;
...@@ -194,8 +215,9 @@ qca8k_write(struct qca8k_priv *priv, u32 reg, u32 val) ...@@ -194,8 +215,9 @@ qca8k_write(struct qca8k_priv *priv, u32 reg, u32 val)
} }
static int static int
qca8k_rmw(struct qca8k_priv *priv, u32 reg, u32 mask, u32 write_val) qca8k_regmap_update_bits(void *ctx, 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;
...@@ -223,34 +245,6 @@ qca8k_rmw(struct qca8k_priv *priv, u32 reg, u32 mask, u32 write_val) ...@@ -223,34 +245,6 @@ qca8k_rmw(struct qca8k_priv *priv, u32 reg, u32 mask, u32 write_val)
return ret; return ret;
} }
static int
qca8k_reg_set(struct qca8k_priv *priv, u32 reg, u32 val)
{
return qca8k_rmw(priv, reg, 0, val);
}
static int
qca8k_reg_clear(struct qca8k_priv *priv, u32 reg, u32 val)
{
return qca8k_rmw(priv, reg, val, 0);
}
static int
qca8k_regmap_read(void *ctx, uint32_t reg, uint32_t *val)
{
struct qca8k_priv *priv = (struct qca8k_priv *)ctx;
return qca8k_read(priv, reg, val);
}
static int
qca8k_regmap_write(void *ctx, uint32_t reg, uint32_t val)
{
struct qca8k_priv *priv = (struct qca8k_priv *)ctx;
return qca8k_write(priv, reg, val);
}
static const struct regmap_range qca8k_readable_ranges[] = { static const struct regmap_range qca8k_readable_ranges[] = {
regmap_reg_range(0x0000, 0x00e4), /* Global control */ regmap_reg_range(0x0000, 0x00e4), /* Global control */
regmap_reg_range(0x0100, 0x0168), /* EEE control */ regmap_reg_range(0x0100, 0x0168), /* EEE control */
...@@ -282,26 +276,19 @@ static struct regmap_config qca8k_regmap_config = { ...@@ -282,26 +276,19 @@ static struct regmap_config qca8k_regmap_config = {
.max_register = 0x16ac, /* end MIB - Port6 range */ .max_register = 0x16ac, /* end MIB - Port6 range */
.reg_read = qca8k_regmap_read, .reg_read = qca8k_regmap_read,
.reg_write = qca8k_regmap_write, .reg_write = qca8k_regmap_write,
.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 */
.cache_type = REGCACHE_NONE, /* Explicitly disable CACHE */
}; };
static int static int
qca8k_busy_wait(struct qca8k_priv *priv, u32 reg, u32 mask) qca8k_busy_wait(struct qca8k_priv *priv, u32 reg, u32 mask)
{ {
int ret, ret1;
u32 val; u32 val;
ret = read_poll_timeout(qca8k_read, ret1, !(val & mask), return regmap_read_poll_timeout(priv->regmap, reg, val, !(val & mask), 0,
0, QCA8K_BUSY_WAIT_TIMEOUT * USEC_PER_MSEC, false, QCA8K_BUSY_WAIT_TIMEOUT * USEC_PER_MSEC);
priv, reg, &val);
/* Check if qca8k_read has failed for a different reason
* before returning -ETIMEDOUT
*/
if (ret < 0 && ret1 < 0)
return ret1;
return ret;
} }
static int static int
...@@ -568,7 +555,7 @@ qca8k_mib_init(struct qca8k_priv *priv) ...@@ -568,7 +555,7 @@ qca8k_mib_init(struct qca8k_priv *priv)
int ret; int ret;
mutex_lock(&priv->reg_mutex); mutex_lock(&priv->reg_mutex);
ret = qca8k_reg_set(priv, QCA8K_REG_MIB, QCA8K_MIB_FLUSH | QCA8K_MIB_BUSY); ret = regmap_set_bits(priv->regmap, QCA8K_REG_MIB, QCA8K_MIB_FLUSH | QCA8K_MIB_BUSY);
if (ret) if (ret)
goto exit; goto exit;
...@@ -576,7 +563,7 @@ qca8k_mib_init(struct qca8k_priv *priv) ...@@ -576,7 +563,7 @@ qca8k_mib_init(struct qca8k_priv *priv)
if (ret) if (ret)
goto exit; goto exit;
ret = qca8k_reg_set(priv, QCA8K_REG_MIB, QCA8K_MIB_CPU_KEEP); ret = regmap_set_bits(priv->regmap, QCA8K_REG_MIB, QCA8K_MIB_CPU_KEEP);
if (ret) if (ret)
goto exit; goto exit;
...@@ -597,9 +584,9 @@ qca8k_port_set_status(struct qca8k_priv *priv, int port, int enable) ...@@ -597,9 +584,9 @@ qca8k_port_set_status(struct qca8k_priv *priv, int port, int enable)
mask |= QCA8K_PORT_STATUS_LINK_AUTO; mask |= QCA8K_PORT_STATUS_LINK_AUTO;
if (enable) if (enable)
qca8k_reg_set(priv, QCA8K_REG_PORT_STATUS(port), mask); regmap_set_bits(priv->regmap, QCA8K_REG_PORT_STATUS(port), mask);
else else
qca8k_reg_clear(priv, QCA8K_REG_PORT_STATUS(port), mask); regmap_clear_bits(priv->regmap, QCA8K_REG_PORT_STATUS(port), mask);
} }
static u32 static u32
...@@ -861,7 +848,7 @@ qca8k_setup_mdio_bus(struct qca8k_priv *priv) ...@@ -861,7 +848,7 @@ qca8k_setup_mdio_bus(struct qca8k_priv *priv)
* a dt-overlay and driver reload changed the configuration * a dt-overlay and driver reload changed the configuration
*/ */
return qca8k_reg_clear(priv, QCA8K_MDIO_MASTER_CTRL, return regmap_clear_bits(priv->regmap, QCA8K_MDIO_MASTER_CTRL,
QCA8K_MDIO_MASTER_EN); QCA8K_MDIO_MASTER_EN);
} }
...@@ -1099,7 +1086,7 @@ qca8k_setup(struct dsa_switch *ds) ...@@ -1099,7 +1086,7 @@ qca8k_setup(struct dsa_switch *ds)
return ret; return ret;
/* Make sure MAC06 is disabled */ /* Make sure MAC06 is disabled */
ret = qca8k_reg_clear(priv, QCA8K_REG_PORT0_PAD_CTRL, ret = regmap_clear_bits(priv->regmap, QCA8K_REG_PORT0_PAD_CTRL,
QCA8K_PORT0_PAD_MAC06_EXCHANGE_EN); QCA8K_PORT0_PAD_MAC06_EXCHANGE_EN);
if (ret) { if (ret) {
dev_err(priv->dev, "failed disabling MAC06 exchange"); dev_err(priv->dev, "failed disabling MAC06 exchange");
...@@ -1107,7 +1094,7 @@ qca8k_setup(struct dsa_switch *ds) ...@@ -1107,7 +1094,7 @@ qca8k_setup(struct dsa_switch *ds)
} }
/* Enable CPU Port */ /* Enable CPU Port */
ret = qca8k_reg_set(priv, QCA8K_REG_GLOBAL_FW_CTRL0, ret = regmap_set_bits(priv->regmap, QCA8K_REG_GLOBAL_FW_CTRL0,
QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN); QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN);
if (ret) { if (ret) {
dev_err(priv->dev, "failed enabling CPU port"); dev_err(priv->dev, "failed enabling CPU port");
...@@ -1176,7 +1163,7 @@ qca8k_setup(struct dsa_switch *ds) ...@@ -1176,7 +1163,7 @@ qca8k_setup(struct dsa_switch *ds)
return ret; return ret;
/* Enable ARP Auto-learning by default */ /* Enable ARP Auto-learning by default */
ret = qca8k_reg_set(priv, QCA8K_PORT_LOOKUP_CTRL(i), ret = regmap_set_bits(priv->regmap, QCA8K_PORT_LOOKUP_CTRL(i),
QCA8K_PORT_LOOKUP_LEARN); QCA8K_PORT_LOOKUP_LEARN);
if (ret) if (ret)
return ret; return ret;
...@@ -1741,7 +1728,7 @@ qca8k_port_bridge_join(struct dsa_switch *ds, int port, struct net_device *br) ...@@ -1741,7 +1728,7 @@ qca8k_port_bridge_join(struct dsa_switch *ds, int port, struct net_device *br)
/* Add this port to the portvlan mask of the other ports /* Add this port to the portvlan mask of the other ports
* in the bridge * in the bridge
*/ */
ret = qca8k_reg_set(priv, ret = regmap_set_bits(priv->regmap,
QCA8K_PORT_LOOKUP_CTRL(i), QCA8K_PORT_LOOKUP_CTRL(i),
BIT(port)); BIT(port));
if (ret) if (ret)
...@@ -1773,7 +1760,7 @@ qca8k_port_bridge_leave(struct dsa_switch *ds, int port, struct net_device *br) ...@@ -1773,7 +1760,7 @@ qca8k_port_bridge_leave(struct dsa_switch *ds, int port, struct net_device *br)
/* Remove this port to the portvlan mask of the other ports /* Remove this port to the portvlan mask of the other ports
* in the bridge * in the bridge
*/ */
qca8k_reg_clear(priv, regmap_clear_bits(priv->regmap,
QCA8K_PORT_LOOKUP_CTRL(i), QCA8K_PORT_LOOKUP_CTRL(i),
BIT(port)); BIT(port));
} }
......
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