mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-19 13:48:06 +00:00
kernel: 5.10: backport qca8k new feature
Backport qca8k new feature: - Ageing configuration support - Add 2 missing counter on qca8337 - Convert to regmap - Standardize define and code with GENMASK AND BITFILED macro - Add mdb add/del support Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
This commit is contained in:
parent
5cf198f764
commit
1e4469b090
@ -0,0 +1,52 @@
|
||||
From 02d6fdecb9c38de19065f6bed8d5214556fd061d Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Thu, 4 Nov 2021 16:00:40 +0100
|
||||
Subject: regmap: allow to define reg_update_bits for no bus configuration
|
||||
|
||||
Some device requires a special handling for reg_update_bits and can't use
|
||||
the normal regmap read write logic. An example is when locking is
|
||||
handled by the device and rmw operations requires to do atomic operations.
|
||||
Allow to declare a dedicated function in regmap_config for
|
||||
reg_update_bits in no bus configuration.
|
||||
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Link: https://lore.kernel.org/r/20211104150040.1260-1-ansuelsmth@gmail.com
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
---
|
||||
drivers/base/regmap/regmap.c | 1 +
|
||||
include/linux/regmap.h | 7 +++++++
|
||||
2 files changed, 8 insertions(+)
|
||||
|
||||
--- a/drivers/base/regmap/regmap.c
|
||||
+++ b/drivers/base/regmap/regmap.c
|
||||
@@ -841,6 +841,7 @@ struct regmap *__regmap_init(struct devi
|
||||
if (!bus) {
|
||||
map->reg_read = config->reg_read;
|
||||
map->reg_write = config->reg_write;
|
||||
+ map->reg_update_bits = config->reg_update_bits;
|
||||
|
||||
map->defer_caching = false;
|
||||
goto skip_format_initialization;
|
||||
--- a/include/linux/regmap.h
|
||||
+++ b/include/linux/regmap.h
|
||||
@@ -289,6 +289,11 @@ typedef void (*regmap_unlock)(void *);
|
||||
* read operation on a bus such as SPI, I2C, etc. Most of the
|
||||
* devices do not need this.
|
||||
* @reg_write: Same as above for writing.
|
||||
+ * @reg_update_bits: Optional callback that if filled will be used to perform
|
||||
+ * all the update_bits(rmw) operation. Should only be provided
|
||||
+ * if the function require special handling with lock and reg
|
||||
+ * handling and the operation cannot be represented as a simple
|
||||
+ * update_bits operation on a bus such as SPI, I2C, etc.
|
||||
* @fast_io: Register IO is fast. Use a spinlock instead of a mutex
|
||||
* to perform locking. This field is ignored if custom lock/unlock
|
||||
* functions are used (see fields lock/unlock of struct regmap_config).
|
||||
@@ -366,6 +371,8 @@ struct regmap_config {
|
||||
|
||||
int (*reg_read)(void *context, unsigned int reg, unsigned int *val);
|
||||
int (*reg_write)(void *context, unsigned int reg, unsigned int val);
|
||||
+ int (*reg_update_bits)(void *context, unsigned int reg,
|
||||
+ unsigned int mask, unsigned int val);
|
||||
|
||||
bool fast_io;
|
||||
|
@ -0,0 +1,508 @@
|
||||
From 90ae68bfc2ffcb54a4ba4f64edbeb84a80cbb57c Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Mon, 22 Nov 2021 16:23:41 +0100
|
||||
Subject: net: dsa: qca8k: convert to GENMASK/FIELD_PREP/FIELD_GET
|
||||
|
||||
Convert and try to standardize bit fields using
|
||||
GENMASK/FIELD_PREP/FIELD_GET macros. Rework some logic to support the
|
||||
standard macro and tidy things up. No functional change intended.
|
||||
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/qca8k.c | 98 +++++++++++++++----------------
|
||||
drivers/net/dsa/qca8k.h | 153 ++++++++++++++++++++++++++----------------------
|
||||
2 files changed, 130 insertions(+), 121 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/qca8k.c
|
||||
+++ b/drivers/net/dsa/qca8k.c
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/phy.h>
|
||||
#include <linux/netdevice.h>
|
||||
+#include <linux/bitfield.h>
|
||||
#include <net/dsa.h>
|
||||
#include <linux/of_net.h>
|
||||
#include <linux/of_mdio.h>
|
||||
@@ -319,18 +320,18 @@ qca8k_fdb_read(struct qca8k_priv *priv,
|
||||
}
|
||||
|
||||
/* vid - 83:72 */
|
||||
- fdb->vid = (reg[2] >> QCA8K_ATU_VID_S) & QCA8K_ATU_VID_M;
|
||||
+ fdb->vid = FIELD_GET(QCA8K_ATU_VID_MASK, reg[2]);
|
||||
/* aging - 67:64 */
|
||||
- fdb->aging = reg[2] & QCA8K_ATU_STATUS_M;
|
||||
+ fdb->aging = FIELD_GET(QCA8K_ATU_STATUS_MASK, reg[2]);
|
||||
/* portmask - 54:48 */
|
||||
- fdb->port_mask = (reg[1] >> QCA8K_ATU_PORT_S) & QCA8K_ATU_PORT_M;
|
||||
+ fdb->port_mask = FIELD_GET(QCA8K_ATU_PORT_MASK, reg[1]);
|
||||
/* mac - 47:0 */
|
||||
- fdb->mac[0] = (reg[1] >> QCA8K_ATU_ADDR0_S) & 0xff;
|
||||
- fdb->mac[1] = reg[1] & 0xff;
|
||||
- fdb->mac[2] = (reg[0] >> QCA8K_ATU_ADDR2_S) & 0xff;
|
||||
- fdb->mac[3] = (reg[0] >> QCA8K_ATU_ADDR3_S) & 0xff;
|
||||
- fdb->mac[4] = (reg[0] >> QCA8K_ATU_ADDR4_S) & 0xff;
|
||||
- fdb->mac[5] = reg[0] & 0xff;
|
||||
+ fdb->mac[0] = FIELD_GET(QCA8K_ATU_ADDR0_MASK, reg[1]);
|
||||
+ fdb->mac[1] = FIELD_GET(QCA8K_ATU_ADDR1_MASK, reg[1]);
|
||||
+ fdb->mac[2] = FIELD_GET(QCA8K_ATU_ADDR2_MASK, reg[0]);
|
||||
+ fdb->mac[3] = FIELD_GET(QCA8K_ATU_ADDR3_MASK, reg[0]);
|
||||
+ fdb->mac[4] = FIELD_GET(QCA8K_ATU_ADDR4_MASK, reg[0]);
|
||||
+ fdb->mac[5] = FIELD_GET(QCA8K_ATU_ADDR5_MASK, reg[0]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -343,18 +344,18 @@ qca8k_fdb_write(struct qca8k_priv *priv,
|
||||
int i;
|
||||
|
||||
/* vid - 83:72 */
|
||||
- reg[2] = (vid & QCA8K_ATU_VID_M) << QCA8K_ATU_VID_S;
|
||||
+ reg[2] = FIELD_PREP(QCA8K_ATU_VID_MASK, vid);
|
||||
/* aging - 67:64 */
|
||||
- reg[2] |= aging & QCA8K_ATU_STATUS_M;
|
||||
+ reg[2] |= FIELD_PREP(QCA8K_ATU_STATUS_MASK, aging);
|
||||
/* portmask - 54:48 */
|
||||
- reg[1] = (port_mask & QCA8K_ATU_PORT_M) << QCA8K_ATU_PORT_S;
|
||||
+ reg[1] = FIELD_PREP(QCA8K_ATU_PORT_MASK, port_mask);
|
||||
/* mac - 47:0 */
|
||||
- reg[1] |= mac[0] << QCA8K_ATU_ADDR0_S;
|
||||
- reg[1] |= mac[1];
|
||||
- reg[0] |= mac[2] << QCA8K_ATU_ADDR2_S;
|
||||
- reg[0] |= mac[3] << QCA8K_ATU_ADDR3_S;
|
||||
- reg[0] |= mac[4] << QCA8K_ATU_ADDR4_S;
|
||||
- reg[0] |= mac[5];
|
||||
+ reg[1] |= FIELD_PREP(QCA8K_ATU_ADDR0_MASK, mac[0]);
|
||||
+ reg[1] |= FIELD_PREP(QCA8K_ATU_ADDR1_MASK, mac[1]);
|
||||
+ reg[0] |= FIELD_PREP(QCA8K_ATU_ADDR2_MASK, mac[2]);
|
||||
+ reg[0] |= FIELD_PREP(QCA8K_ATU_ADDR3_MASK, mac[3]);
|
||||
+ reg[0] |= FIELD_PREP(QCA8K_ATU_ADDR4_MASK, mac[4]);
|
||||
+ reg[0] |= FIELD_PREP(QCA8K_ATU_ADDR5_MASK, mac[5]);
|
||||
|
||||
/* load the array into the ARL table */
|
||||
for (i = 0; i < 3; i++)
|
||||
@@ -372,7 +373,7 @@ qca8k_fdb_access(struct qca8k_priv *priv
|
||||
reg |= cmd;
|
||||
if (port >= 0) {
|
||||
reg |= QCA8K_ATU_FUNC_PORT_EN;
|
||||
- reg |= (port & QCA8K_ATU_FUNC_PORT_M) << QCA8K_ATU_FUNC_PORT_S;
|
||||
+ reg |= FIELD_PREP(QCA8K_ATU_FUNC_PORT_MASK, port);
|
||||
}
|
||||
|
||||
/* Write the function register triggering the table access */
|
||||
@@ -454,7 +455,7 @@ qca8k_vlan_access(struct qca8k_priv *pri
|
||||
/* Set the command and VLAN index */
|
||||
reg = QCA8K_VTU_FUNC1_BUSY;
|
||||
reg |= cmd;
|
||||
- reg |= vid << QCA8K_VTU_FUNC1_VID_S;
|
||||
+ reg |= FIELD_PREP(QCA8K_VTU_FUNC1_VID_MASK, vid);
|
||||
|
||||
/* Write the function register triggering the table access */
|
||||
ret = qca8k_write(priv, QCA8K_REG_VTU_FUNC1, reg);
|
||||
@@ -500,13 +501,11 @@ qca8k_vlan_add(struct qca8k_priv *priv,
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
reg |= QCA8K_VTU_FUNC0_VALID | QCA8K_VTU_FUNC0_IVL_EN;
|
||||
- reg &= ~(QCA8K_VTU_FUNC0_EG_MODE_MASK << QCA8K_VTU_FUNC0_EG_MODE_S(port));
|
||||
+ reg &= ~QCA8K_VTU_FUNC0_EG_MODE_PORT_MASK(port);
|
||||
if (untagged)
|
||||
- reg |= QCA8K_VTU_FUNC0_EG_MODE_UNTAG <<
|
||||
- QCA8K_VTU_FUNC0_EG_MODE_S(port);
|
||||
+ reg |= QCA8K_VTU_FUNC0_EG_MODE_PORT_UNTAG(port);
|
||||
else
|
||||
- reg |= QCA8K_VTU_FUNC0_EG_MODE_TAG <<
|
||||
- QCA8K_VTU_FUNC0_EG_MODE_S(port);
|
||||
+ reg |= QCA8K_VTU_FUNC0_EG_MODE_PORT_TAG(port);
|
||||
|
||||
ret = qca8k_write(priv, QCA8K_REG_VTU_FUNC0, reg);
|
||||
if (ret)
|
||||
@@ -534,15 +533,13 @@ qca8k_vlan_del(struct qca8k_priv *priv,
|
||||
ret = qca8k_read(priv, QCA8K_REG_VTU_FUNC0, ®);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
- reg &= ~(3 << QCA8K_VTU_FUNC0_EG_MODE_S(port));
|
||||
- reg |= QCA8K_VTU_FUNC0_EG_MODE_NOT <<
|
||||
- QCA8K_VTU_FUNC0_EG_MODE_S(port);
|
||||
+ reg &= ~QCA8K_VTU_FUNC0_EG_MODE_PORT_MASK(port);
|
||||
+ reg |= QCA8K_VTU_FUNC0_EG_MODE_PORT_NOT(port);
|
||||
|
||||
/* Check if we're the last member to be removed */
|
||||
del = true;
|
||||
for (i = 0; i < QCA8K_NUM_PORTS; i++) {
|
||||
- mask = QCA8K_VTU_FUNC0_EG_MODE_NOT;
|
||||
- mask <<= QCA8K_VTU_FUNC0_EG_MODE_S(i);
|
||||
+ mask = QCA8K_VTU_FUNC0_EG_MODE_PORT_NOT(i);
|
||||
|
||||
if ((reg & mask) != mask) {
|
||||
del = false;
|
||||
@@ -1014,7 +1011,7 @@ qca8k_parse_port_config(struct qca8k_pri
|
||||
mode == PHY_INTERFACE_MODE_RGMII_TXID)
|
||||
delay = 1;
|
||||
|
||||
- if (delay > QCA8K_MAX_DELAY) {
|
||||
+ if (!FIELD_FIT(QCA8K_PORT_PAD_RGMII_TX_DELAY_MASK, delay)) {
|
||||
dev_err(priv->dev, "rgmii tx delay is limited to a max value of 3ns, setting to the max value");
|
||||
delay = 3;
|
||||
}
|
||||
@@ -1030,7 +1027,7 @@ qca8k_parse_port_config(struct qca8k_pri
|
||||
mode == PHY_INTERFACE_MODE_RGMII_RXID)
|
||||
delay = 2;
|
||||
|
||||
- if (delay > QCA8K_MAX_DELAY) {
|
||||
+ if (!FIELD_FIT(QCA8K_PORT_PAD_RGMII_RX_DELAY_MASK, delay)) {
|
||||
dev_err(priv->dev, "rgmii rx delay is limited to a max value of 3ns, setting to the max value");
|
||||
delay = 3;
|
||||
}
|
||||
@@ -1141,8 +1138,8 @@ qca8k_setup(struct dsa_switch *ds)
|
||||
/* Enable QCA header mode on all cpu ports */
|
||||
if (dsa_is_cpu_port(ds, i)) {
|
||||
ret = qca8k_write(priv, QCA8K_REG_PORT_HDR_CTRL(i),
|
||||
- QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_TX_S |
|
||||
- QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_RX_S);
|
||||
+ FIELD_PREP(QCA8K_PORT_HDR_CTRL_TX_MASK, QCA8K_PORT_HDR_CTRL_ALL) |
|
||||
+ FIELD_PREP(QCA8K_PORT_HDR_CTRL_RX_MASK, QCA8K_PORT_HDR_CTRL_ALL));
|
||||
if (ret) {
|
||||
dev_err(priv->dev, "failed enabling QCA header mode");
|
||||
return ret;
|
||||
@@ -1159,10 +1156,10 @@ qca8k_setup(struct dsa_switch *ds)
|
||||
* for igmp, unknown, multicast and broadcast packet
|
||||
*/
|
||||
ret = qca8k_write(priv, QCA8K_REG_GLOBAL_FW_CTRL1,
|
||||
- BIT(cpu_port) << QCA8K_GLOBAL_FW_CTRL1_IGMP_DP_S |
|
||||
- BIT(cpu_port) << QCA8K_GLOBAL_FW_CTRL1_BC_DP_S |
|
||||
- BIT(cpu_port) << QCA8K_GLOBAL_FW_CTRL1_MC_DP_S |
|
||||
- BIT(cpu_port) << QCA8K_GLOBAL_FW_CTRL1_UC_DP_S);
|
||||
+ FIELD_PREP(QCA8K_GLOBAL_FW_CTRL1_IGMP_DP_MASK, BIT(cpu_port)) |
|
||||
+ FIELD_PREP(QCA8K_GLOBAL_FW_CTRL1_BC_DP_MASK, BIT(cpu_port)) |
|
||||
+ FIELD_PREP(QCA8K_GLOBAL_FW_CTRL1_MC_DP_MASK, BIT(cpu_port)) |
|
||||
+ FIELD_PREP(QCA8K_GLOBAL_FW_CTRL1_UC_DP_MASK, BIT(cpu_port)));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -1180,8 +1177,6 @@ qca8k_setup(struct dsa_switch *ds)
|
||||
|
||||
/* Individual user ports get connected to CPU port only */
|
||||
if (dsa_is_user_port(ds, i)) {
|
||||
- int shift = 16 * (i % 2);
|
||||
-
|
||||
ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i),
|
||||
QCA8K_PORT_LOOKUP_MEMBER,
|
||||
BIT(cpu_port));
|
||||
@@ -1198,8 +1193,8 @@ qca8k_setup(struct dsa_switch *ds)
|
||||
* default egress vid
|
||||
*/
|
||||
ret = qca8k_rmw(priv, QCA8K_EGRESS_VLAN(i),
|
||||
- 0xfff << shift,
|
||||
- QCA8K_PORT_VID_DEF << shift);
|
||||
+ QCA8K_EGREES_VLAN_PORT_MASK(i),
|
||||
+ QCA8K_EGREES_VLAN_PORT(i, QCA8K_PORT_VID_DEF));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -1246,7 +1241,7 @@ qca8k_setup(struct dsa_switch *ds)
|
||||
QCA8K_PORT_HOL_CTRL1_EG_PORT_BUF_EN |
|
||||
QCA8K_PORT_HOL_CTRL1_WRED_EN;
|
||||
qca8k_rmw(priv, QCA8K_REG_PORT_HOL_CTRL1(i),
|
||||
- QCA8K_PORT_HOL_CTRL1_ING_BUF |
|
||||
+ QCA8K_PORT_HOL_CTRL1_ING_BUF_MASK |
|
||||
QCA8K_PORT_HOL_CTRL1_EG_PRI_BUF_EN |
|
||||
QCA8K_PORT_HOL_CTRL1_EG_PORT_BUF_EN |
|
||||
QCA8K_PORT_HOL_CTRL1_WRED_EN,
|
||||
@@ -1269,8 +1264,8 @@ qca8k_setup(struct dsa_switch *ds)
|
||||
mask = QCA8K_GLOBAL_FC_GOL_XON_THRES(288) |
|
||||
QCA8K_GLOBAL_FC_GOL_XOFF_THRES(496);
|
||||
qca8k_rmw(priv, QCA8K_REG_GLOBAL_FC_THRESH,
|
||||
- QCA8K_GLOBAL_FC_GOL_XON_THRES_S |
|
||||
- QCA8K_GLOBAL_FC_GOL_XOFF_THRES_S,
|
||||
+ QCA8K_GLOBAL_FC_GOL_XON_THRES_MASK |
|
||||
+ QCA8K_GLOBAL_FC_GOL_XOFF_THRES_MASK,
|
||||
mask);
|
||||
}
|
||||
|
||||
@@ -1918,11 +1913,11 @@ qca8k_port_vlan_filtering(struct dsa_swi
|
||||
|
||||
if (vlan_filtering) {
|
||||
qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
|
||||
- QCA8K_PORT_LOOKUP_VLAN_MODE,
|
||||
+ QCA8K_PORT_LOOKUP_VLAN_MODE_MASK,
|
||||
QCA8K_PORT_LOOKUP_VLAN_MODE_SECURE);
|
||||
} else {
|
||||
qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
|
||||
- QCA8K_PORT_LOOKUP_VLAN_MODE,
|
||||
+ QCA8K_PORT_LOOKUP_VLAN_MODE_MASK,
|
||||
QCA8K_PORT_LOOKUP_VLAN_MODE_NONE);
|
||||
}
|
||||
|
||||
@@ -1953,11 +1948,9 @@ qca8k_port_vlan_add(struct dsa_switch *d
|
||||
dev_err(priv->dev, "Failed to add VLAN to port %d (%d)", port, ret);
|
||||
|
||||
if (pvid) {
|
||||
- int shift = 16 * (port % 2);
|
||||
-
|
||||
qca8k_rmw(priv, QCA8K_EGRESS_VLAN(port),
|
||||
- 0xfff << shift,
|
||||
- vlan->vid_end << shift);
|
||||
+ QCA8K_EGREES_VLAN_PORT_MASK(port),
|
||||
+ QCA8K_EGREES_VLAN_PORT(port, vlan->vid_end));
|
||||
qca8k_write(priv, QCA8K_REG_PORT_VLAN_CTRL0(port),
|
||||
QCA8K_PORT_VLAN_CVID(vlan->vid_end) |
|
||||
QCA8K_PORT_VLAN_SVID(vlan->vid_end));
|
||||
@@ -2050,7 +2043,7 @@ static int qca8k_read_switch_id(struct q
|
||||
if (ret < 0)
|
||||
return -ENODEV;
|
||||
|
||||
- id = QCA8K_MASK_CTRL_DEVICE_ID(val & QCA8K_MASK_CTRL_DEVICE_ID_MASK);
|
||||
+ id = QCA8K_MASK_CTRL_DEVICE_ID(val);
|
||||
if (id != data->id) {
|
||||
dev_err(priv->dev, "Switch id detected %x but expected %x", id, data->id);
|
||||
return -ENODEV;
|
||||
@@ -2059,7 +2052,7 @@ static int qca8k_read_switch_id(struct q
|
||||
priv->switch_id = id;
|
||||
|
||||
/* Save revision to communicate to the internal PHY driver */
|
||||
- priv->switch_revision = (val & QCA8K_MASK_CTRL_REV_ID_MASK);
|
||||
+ priv->switch_revision = QCA8K_MASK_CTRL_REV_ID(val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
--- a/drivers/net/dsa/qca8k.h
|
||||
+++ b/drivers/net/dsa/qca8k.h
|
||||
@@ -30,9 +30,9 @@
|
||||
/* Global control registers */
|
||||
#define QCA8K_REG_MASK_CTRL 0x000
|
||||
#define QCA8K_MASK_CTRL_REV_ID_MASK GENMASK(7, 0)
|
||||
-#define QCA8K_MASK_CTRL_REV_ID(x) ((x) >> 0)
|
||||
+#define QCA8K_MASK_CTRL_REV_ID(x) FIELD_GET(QCA8K_MASK_CTRL_REV_ID_MASK, x)
|
||||
#define QCA8K_MASK_CTRL_DEVICE_ID_MASK GENMASK(15, 8)
|
||||
-#define QCA8K_MASK_CTRL_DEVICE_ID(x) ((x) >> 8)
|
||||
+#define QCA8K_MASK_CTRL_DEVICE_ID(x) FIELD_GET(QCA8K_MASK_CTRL_DEVICE_ID_MASK, x)
|
||||
#define QCA8K_REG_PORT0_PAD_CTRL 0x004
|
||||
#define QCA8K_PORT0_PAD_MAC06_EXCHANGE_EN BIT(31)
|
||||
#define QCA8K_PORT0_PAD_SGMII_RXCLK_FALLING_EDGE BIT(19)
|
||||
@@ -41,12 +41,11 @@
|
||||
#define QCA8K_REG_PORT6_PAD_CTRL 0x00c
|
||||
#define QCA8K_PORT_PAD_RGMII_EN BIT(26)
|
||||
#define QCA8K_PORT_PAD_RGMII_TX_DELAY_MASK GENMASK(23, 22)
|
||||
-#define QCA8K_PORT_PAD_RGMII_TX_DELAY(x) ((x) << 22)
|
||||
+#define QCA8K_PORT_PAD_RGMII_TX_DELAY(x) FIELD_PREP(QCA8K_PORT_PAD_RGMII_TX_DELAY_MASK, x)
|
||||
#define QCA8K_PORT_PAD_RGMII_RX_DELAY_MASK GENMASK(21, 20)
|
||||
-#define QCA8K_PORT_PAD_RGMII_RX_DELAY(x) ((x) << 20)
|
||||
+#define QCA8K_PORT_PAD_RGMII_RX_DELAY(x) FIELD_PREP(QCA8K_PORT_PAD_RGMII_RX_DELAY_MASK, x)
|
||||
#define QCA8K_PORT_PAD_RGMII_TX_DELAY_EN BIT(25)
|
||||
#define QCA8K_PORT_PAD_RGMII_RX_DELAY_EN BIT(24)
|
||||
-#define QCA8K_MAX_DELAY 3
|
||||
#define QCA8K_PORT_PAD_SGMII_EN BIT(7)
|
||||
#define QCA8K_REG_PWS 0x010
|
||||
#define QCA8K_PWS_POWER_ON_SEL BIT(31)
|
||||
@@ -68,10 +67,12 @@
|
||||
#define QCA8K_MDIO_MASTER_READ BIT(27)
|
||||
#define QCA8K_MDIO_MASTER_WRITE 0
|
||||
#define QCA8K_MDIO_MASTER_SUP_PRE BIT(26)
|
||||
-#define QCA8K_MDIO_MASTER_PHY_ADDR(x) ((x) << 21)
|
||||
-#define QCA8K_MDIO_MASTER_REG_ADDR(x) ((x) << 16)
|
||||
-#define QCA8K_MDIO_MASTER_DATA(x) (x)
|
||||
+#define QCA8K_MDIO_MASTER_PHY_ADDR_MASK GENMASK(25, 21)
|
||||
+#define QCA8K_MDIO_MASTER_PHY_ADDR(x) FIELD_PREP(QCA8K_MDIO_MASTER_PHY_ADDR_MASK, x)
|
||||
+#define QCA8K_MDIO_MASTER_REG_ADDR_MASK GENMASK(20, 16)
|
||||
+#define QCA8K_MDIO_MASTER_REG_ADDR(x) FIELD_PREP(QCA8K_MDIO_MASTER_REG_ADDR_MASK, x)
|
||||
#define QCA8K_MDIO_MASTER_DATA_MASK GENMASK(15, 0)
|
||||
+#define QCA8K_MDIO_MASTER_DATA(x) FIELD_PREP(QCA8K_MDIO_MASTER_DATA_MASK, x)
|
||||
#define QCA8K_MDIO_MASTER_MAX_PORTS 5
|
||||
#define QCA8K_MDIO_MASTER_MAX_REG 32
|
||||
#define QCA8K_GOL_MAC_ADDR0 0x60
|
||||
@@ -93,9 +94,7 @@
|
||||
#define QCA8K_PORT_STATUS_FLOW_AUTO BIT(12)
|
||||
#define QCA8K_REG_PORT_HDR_CTRL(_i) (0x9c + (_i * 4))
|
||||
#define QCA8K_PORT_HDR_CTRL_RX_MASK GENMASK(3, 2)
|
||||
-#define QCA8K_PORT_HDR_CTRL_RX_S 2
|
||||
#define QCA8K_PORT_HDR_CTRL_TX_MASK GENMASK(1, 0)
|
||||
-#define QCA8K_PORT_HDR_CTRL_TX_S 0
|
||||
#define QCA8K_PORT_HDR_CTRL_ALL 2
|
||||
#define QCA8K_PORT_HDR_CTRL_MGMT 1
|
||||
#define QCA8K_PORT_HDR_CTRL_NONE 0
|
||||
@@ -105,10 +104,11 @@
|
||||
#define QCA8K_SGMII_EN_TX BIT(3)
|
||||
#define QCA8K_SGMII_EN_SD BIT(4)
|
||||
#define QCA8K_SGMII_CLK125M_DELAY BIT(7)
|
||||
-#define QCA8K_SGMII_MODE_CTRL_MASK (BIT(22) | BIT(23))
|
||||
-#define QCA8K_SGMII_MODE_CTRL_BASEX (0 << 22)
|
||||
-#define QCA8K_SGMII_MODE_CTRL_PHY (1 << 22)
|
||||
-#define QCA8K_SGMII_MODE_CTRL_MAC (2 << 22)
|
||||
+#define QCA8K_SGMII_MODE_CTRL_MASK GENMASK(23, 22)
|
||||
+#define QCA8K_SGMII_MODE_CTRL(x) FIELD_PREP(QCA8K_SGMII_MODE_CTRL_MASK, x)
|
||||
+#define QCA8K_SGMII_MODE_CTRL_BASEX QCA8K_SGMII_MODE_CTRL(0x0)
|
||||
+#define QCA8K_SGMII_MODE_CTRL_PHY QCA8K_SGMII_MODE_CTRL(0x1)
|
||||
+#define QCA8K_SGMII_MODE_CTRL_MAC QCA8K_SGMII_MODE_CTRL(0x2)
|
||||
|
||||
/* MAC_PWR_SEL registers */
|
||||
#define QCA8K_REG_MAC_PWR_SEL 0x0e4
|
||||
@@ -121,100 +121,115 @@
|
||||
|
||||
/* ACL registers */
|
||||
#define QCA8K_REG_PORT_VLAN_CTRL0(_i) (0x420 + (_i * 8))
|
||||
-#define QCA8K_PORT_VLAN_CVID(x) (x << 16)
|
||||
-#define QCA8K_PORT_VLAN_SVID(x) x
|
||||
+#define QCA8K_PORT_VLAN_CVID_MASK GENMASK(27, 16)
|
||||
+#define QCA8K_PORT_VLAN_CVID(x) FIELD_PREP(QCA8K_PORT_VLAN_CVID_MASK, x)
|
||||
+#define QCA8K_PORT_VLAN_SVID_MASK GENMASK(11, 0)
|
||||
+#define QCA8K_PORT_VLAN_SVID(x) FIELD_PREP(QCA8K_PORT_VLAN_SVID_MASK, x)
|
||||
#define QCA8K_REG_PORT_VLAN_CTRL1(_i) (0x424 + (_i * 8))
|
||||
#define QCA8K_REG_IPV4_PRI_BASE_ADDR 0x470
|
||||
#define QCA8K_REG_IPV4_PRI_ADDR_MASK 0x474
|
||||
|
||||
/* Lookup registers */
|
||||
#define QCA8K_REG_ATU_DATA0 0x600
|
||||
-#define QCA8K_ATU_ADDR2_S 24
|
||||
-#define QCA8K_ATU_ADDR3_S 16
|
||||
-#define QCA8K_ATU_ADDR4_S 8
|
||||
+#define QCA8K_ATU_ADDR2_MASK GENMASK(31, 24)
|
||||
+#define QCA8K_ATU_ADDR3_MASK GENMASK(23, 16)
|
||||
+#define QCA8K_ATU_ADDR4_MASK GENMASK(15, 8)
|
||||
+#define QCA8K_ATU_ADDR5_MASK GENMASK(7, 0)
|
||||
#define QCA8K_REG_ATU_DATA1 0x604
|
||||
-#define QCA8K_ATU_PORT_M 0x7f
|
||||
-#define QCA8K_ATU_PORT_S 16
|
||||
-#define QCA8K_ATU_ADDR0_S 8
|
||||
+#define QCA8K_ATU_PORT_MASK GENMASK(22, 16)
|
||||
+#define QCA8K_ATU_ADDR0_MASK GENMASK(15, 8)
|
||||
+#define QCA8K_ATU_ADDR1_MASK GENMASK(7, 0)
|
||||
#define QCA8K_REG_ATU_DATA2 0x608
|
||||
-#define QCA8K_ATU_VID_M 0xfff
|
||||
-#define QCA8K_ATU_VID_S 8
|
||||
-#define QCA8K_ATU_STATUS_M 0xf
|
||||
+#define QCA8K_ATU_VID_MASK GENMASK(19, 8)
|
||||
+#define QCA8K_ATU_STATUS_MASK GENMASK(3, 0)
|
||||
#define QCA8K_ATU_STATUS_STATIC 0xf
|
||||
#define QCA8K_REG_ATU_FUNC 0x60c
|
||||
#define QCA8K_ATU_FUNC_BUSY BIT(31)
|
||||
#define QCA8K_ATU_FUNC_PORT_EN BIT(14)
|
||||
#define QCA8K_ATU_FUNC_MULTI_EN BIT(13)
|
||||
#define QCA8K_ATU_FUNC_FULL BIT(12)
|
||||
-#define QCA8K_ATU_FUNC_PORT_M 0xf
|
||||
-#define QCA8K_ATU_FUNC_PORT_S 8
|
||||
+#define QCA8K_ATU_FUNC_PORT_MASK GENMASK(11, 8)
|
||||
#define QCA8K_REG_VTU_FUNC0 0x610
|
||||
#define QCA8K_VTU_FUNC0_VALID BIT(20)
|
||||
#define QCA8K_VTU_FUNC0_IVL_EN BIT(19)
|
||||
-#define QCA8K_VTU_FUNC0_EG_MODE_S(_i) (4 + (_i) * 2)
|
||||
-#define QCA8K_VTU_FUNC0_EG_MODE_MASK 3
|
||||
-#define QCA8K_VTU_FUNC0_EG_MODE_UNMOD 0
|
||||
-#define QCA8K_VTU_FUNC0_EG_MODE_UNTAG 1
|
||||
-#define QCA8K_VTU_FUNC0_EG_MODE_TAG 2
|
||||
-#define QCA8K_VTU_FUNC0_EG_MODE_NOT 3
|
||||
+/* QCA8K_VTU_FUNC0_EG_MODE_MASK GENMASK(17, 4)
|
||||
+ * It does contain VLAN_MODE for each port [5:4] for port0,
|
||||
+ * [7:6] for port1 ... [17:16] for port6. Use virtual port
|
||||
+ * define to handle this.
|
||||
+ */
|
||||
+#define QCA8K_VTU_FUNC0_EG_MODE_PORT_SHIFT(_i) (4 + (_i) * 2)
|
||||
+#define QCA8K_VTU_FUNC0_EG_MODE_MASK GENMASK(1, 0)
|
||||
+#define QCA8K_VTU_FUNC0_EG_MODE_PORT_MASK(_i) (GENMASK(1, 0) << QCA8K_VTU_FUNC0_EG_MODE_PORT_SHIFT(_i))
|
||||
+#define QCA8K_VTU_FUNC0_EG_MODE_UNMOD FIELD_PREP(QCA8K_VTU_FUNC0_EG_MODE_MASK, 0x0)
|
||||
+#define QCA8K_VTU_FUNC0_EG_MODE_PORT_UNMOD(_i) (QCA8K_VTU_FUNC0_EG_MODE_UNMOD << QCA8K_VTU_FUNC0_EG_MODE_PORT_SHIFT(_i))
|
||||
+#define QCA8K_VTU_FUNC0_EG_MODE_UNTAG FIELD_PREP(QCA8K_VTU_FUNC0_EG_MODE_MASK, 0x1)
|
||||
+#define QCA8K_VTU_FUNC0_EG_MODE_PORT_UNTAG(_i) (QCA8K_VTU_FUNC0_EG_MODE_UNTAG << QCA8K_VTU_FUNC0_EG_MODE_PORT_SHIFT(_i))
|
||||
+#define QCA8K_VTU_FUNC0_EG_MODE_TAG FIELD_PREP(QCA8K_VTU_FUNC0_EG_MODE_MASK, 0x2)
|
||||
+#define QCA8K_VTU_FUNC0_EG_MODE_PORT_TAG(_i) (QCA8K_VTU_FUNC0_EG_MODE_TAG << QCA8K_VTU_FUNC0_EG_MODE_PORT_SHIFT(_i))
|
||||
+#define QCA8K_VTU_FUNC0_EG_MODE_NOT FIELD_PREP(QCA8K_VTU_FUNC0_EG_MODE_MASK, 0x3)
|
||||
+#define QCA8K_VTU_FUNC0_EG_MODE_PORT_NOT(_i) (QCA8K_VTU_FUNC0_EG_MODE_NOT << QCA8K_VTU_FUNC0_EG_MODE_PORT_SHIFT(_i))
|
||||
#define QCA8K_REG_VTU_FUNC1 0x614
|
||||
#define QCA8K_VTU_FUNC1_BUSY BIT(31)
|
||||
-#define QCA8K_VTU_FUNC1_VID_S 16
|
||||
+#define QCA8K_VTU_FUNC1_VID_MASK GENMASK(27, 16)
|
||||
#define QCA8K_VTU_FUNC1_FULL BIT(4)
|
||||
#define QCA8K_REG_GLOBAL_FW_CTRL0 0x620
|
||||
#define QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN BIT(10)
|
||||
#define QCA8K_REG_GLOBAL_FW_CTRL1 0x624
|
||||
-#define QCA8K_GLOBAL_FW_CTRL1_IGMP_DP_S 24
|
||||
-#define QCA8K_GLOBAL_FW_CTRL1_BC_DP_S 16
|
||||
-#define QCA8K_GLOBAL_FW_CTRL1_MC_DP_S 8
|
||||
-#define QCA8K_GLOBAL_FW_CTRL1_UC_DP_S 0
|
||||
+#define QCA8K_GLOBAL_FW_CTRL1_IGMP_DP_MASK GENMASK(30, 24)
|
||||
+#define QCA8K_GLOBAL_FW_CTRL1_BC_DP_MASK GENMASK(22, 16)
|
||||
+#define QCA8K_GLOBAL_FW_CTRL1_MC_DP_MASK GENMASK(14, 8)
|
||||
+#define QCA8K_GLOBAL_FW_CTRL1_UC_DP_MASK GENMASK(6, 0)
|
||||
#define QCA8K_PORT_LOOKUP_CTRL(_i) (0x660 + (_i) * 0xc)
|
||||
#define QCA8K_PORT_LOOKUP_MEMBER GENMASK(6, 0)
|
||||
-#define QCA8K_PORT_LOOKUP_VLAN_MODE GENMASK(9, 8)
|
||||
-#define QCA8K_PORT_LOOKUP_VLAN_MODE_NONE (0 << 8)
|
||||
-#define QCA8K_PORT_LOOKUP_VLAN_MODE_FALLBACK (1 << 8)
|
||||
-#define QCA8K_PORT_LOOKUP_VLAN_MODE_CHECK (2 << 8)
|
||||
-#define QCA8K_PORT_LOOKUP_VLAN_MODE_SECURE (3 << 8)
|
||||
+#define QCA8K_PORT_LOOKUP_VLAN_MODE_MASK GENMASK(9, 8)
|
||||
+#define QCA8K_PORT_LOOKUP_VLAN_MODE(x) FIELD_PREP(QCA8K_PORT_LOOKUP_VLAN_MODE_MASK, x)
|
||||
+#define QCA8K_PORT_LOOKUP_VLAN_MODE_NONE QCA8K_PORT_LOOKUP_VLAN_MODE(0x0)
|
||||
+#define QCA8K_PORT_LOOKUP_VLAN_MODE_FALLBACK QCA8K_PORT_LOOKUP_VLAN_MODE(0x1)
|
||||
+#define QCA8K_PORT_LOOKUP_VLAN_MODE_CHECK QCA8K_PORT_LOOKUP_VLAN_MODE(0x2)
|
||||
+#define QCA8K_PORT_LOOKUP_VLAN_MODE_SECURE QCA8K_PORT_LOOKUP_VLAN_MODE(0x3)
|
||||
#define QCA8K_PORT_LOOKUP_STATE_MASK GENMASK(18, 16)
|
||||
-#define QCA8K_PORT_LOOKUP_STATE_DISABLED (0 << 16)
|
||||
-#define QCA8K_PORT_LOOKUP_STATE_BLOCKING (1 << 16)
|
||||
-#define QCA8K_PORT_LOOKUP_STATE_LISTENING (2 << 16)
|
||||
-#define QCA8K_PORT_LOOKUP_STATE_LEARNING (3 << 16)
|
||||
-#define QCA8K_PORT_LOOKUP_STATE_FORWARD (4 << 16)
|
||||
-#define QCA8K_PORT_LOOKUP_STATE GENMASK(18, 16)
|
||||
+#define QCA8K_PORT_LOOKUP_STATE(x) FIELD_PREP(QCA8K_PORT_LOOKUP_STATE_MASK, x)
|
||||
+#define QCA8K_PORT_LOOKUP_STATE_DISABLED QCA8K_PORT_LOOKUP_STATE(0x0)
|
||||
+#define QCA8K_PORT_LOOKUP_STATE_BLOCKING QCA8K_PORT_LOOKUP_STATE(0x1)
|
||||
+#define QCA8K_PORT_LOOKUP_STATE_LISTENING QCA8K_PORT_LOOKUP_STATE(0x2)
|
||||
+#define QCA8K_PORT_LOOKUP_STATE_LEARNING QCA8K_PORT_LOOKUP_STATE(0x3)
|
||||
+#define QCA8K_PORT_LOOKUP_STATE_FORWARD QCA8K_PORT_LOOKUP_STATE(0x4)
|
||||
#define QCA8K_PORT_LOOKUP_LEARN BIT(20)
|
||||
|
||||
#define QCA8K_REG_GLOBAL_FC_THRESH 0x800
|
||||
-#define QCA8K_GLOBAL_FC_GOL_XON_THRES(x) ((x) << 16)
|
||||
-#define QCA8K_GLOBAL_FC_GOL_XON_THRES_S GENMASK(24, 16)
|
||||
-#define QCA8K_GLOBAL_FC_GOL_XOFF_THRES(x) ((x) << 0)
|
||||
-#define QCA8K_GLOBAL_FC_GOL_XOFF_THRES_S GENMASK(8, 0)
|
||||
+#define QCA8K_GLOBAL_FC_GOL_XON_THRES_MASK GENMASK(24, 16)
|
||||
+#define QCA8K_GLOBAL_FC_GOL_XON_THRES(x) FIELD_PREP(QCA8K_GLOBAL_FC_GOL_XON_THRES_MASK, x)
|
||||
+#define QCA8K_GLOBAL_FC_GOL_XOFF_THRES_MASK GENMASK(8, 0)
|
||||
+#define QCA8K_GLOBAL_FC_GOL_XOFF_THRES(x) FIELD_PREP(QCA8K_GLOBAL_FC_GOL_XOFF_THRES_MASK, x)
|
||||
|
||||
#define QCA8K_REG_PORT_HOL_CTRL0(_i) (0x970 + (_i) * 0x8)
|
||||
-#define QCA8K_PORT_HOL_CTRL0_EG_PRI0_BUF GENMASK(3, 0)
|
||||
-#define QCA8K_PORT_HOL_CTRL0_EG_PRI0(x) ((x) << 0)
|
||||
-#define QCA8K_PORT_HOL_CTRL0_EG_PRI1_BUF GENMASK(7, 4)
|
||||
-#define QCA8K_PORT_HOL_CTRL0_EG_PRI1(x) ((x) << 4)
|
||||
-#define QCA8K_PORT_HOL_CTRL0_EG_PRI2_BUF GENMASK(11, 8)
|
||||
-#define QCA8K_PORT_HOL_CTRL0_EG_PRI2(x) ((x) << 8)
|
||||
-#define QCA8K_PORT_HOL_CTRL0_EG_PRI3_BUF GENMASK(15, 12)
|
||||
-#define QCA8K_PORT_HOL_CTRL0_EG_PRI3(x) ((x) << 12)
|
||||
-#define QCA8K_PORT_HOL_CTRL0_EG_PRI4_BUF GENMASK(19, 16)
|
||||
-#define QCA8K_PORT_HOL_CTRL0_EG_PRI4(x) ((x) << 16)
|
||||
-#define QCA8K_PORT_HOL_CTRL0_EG_PRI5_BUF GENMASK(23, 20)
|
||||
-#define QCA8K_PORT_HOL_CTRL0_EG_PRI5(x) ((x) << 20)
|
||||
-#define QCA8K_PORT_HOL_CTRL0_EG_PORT_BUF GENMASK(29, 24)
|
||||
-#define QCA8K_PORT_HOL_CTRL0_EG_PORT(x) ((x) << 24)
|
||||
+#define QCA8K_PORT_HOL_CTRL0_EG_PRI0_BUF_MASK GENMASK(3, 0)
|
||||
+#define QCA8K_PORT_HOL_CTRL0_EG_PRI0(x) FIELD_PREP(QCA8K_PORT_HOL_CTRL0_EG_PRI0_BUF_MASK, x)
|
||||
+#define QCA8K_PORT_HOL_CTRL0_EG_PRI1_BUF_MASK GENMASK(7, 4)
|
||||
+#define QCA8K_PORT_HOL_CTRL0_EG_PRI1(x) FIELD_PREP(QCA8K_PORT_HOL_CTRL0_EG_PRI1_BUF_MASK, x)
|
||||
+#define QCA8K_PORT_HOL_CTRL0_EG_PRI2_BUF_MASK GENMASK(11, 8)
|
||||
+#define QCA8K_PORT_HOL_CTRL0_EG_PRI2(x) FIELD_PREP(QCA8K_PORT_HOL_CTRL0_EG_PRI2_BUF_MASK, x)
|
||||
+#define QCA8K_PORT_HOL_CTRL0_EG_PRI3_BUF_MASK GENMASK(15, 12)
|
||||
+#define QCA8K_PORT_HOL_CTRL0_EG_PRI3(x) FIELD_PREP(QCA8K_PORT_HOL_CTRL0_EG_PRI3_BUF_MASK, x)
|
||||
+#define QCA8K_PORT_HOL_CTRL0_EG_PRI4_BUF_MASK GENMASK(19, 16)
|
||||
+#define QCA8K_PORT_HOL_CTRL0_EG_PRI4(x) FIELD_PREP(QCA8K_PORT_HOL_CTRL0_EG_PRI4_BUF_MASK, x)
|
||||
+#define QCA8K_PORT_HOL_CTRL0_EG_PRI5_BUF_MASK GENMASK(23, 20)
|
||||
+#define QCA8K_PORT_HOL_CTRL0_EG_PRI5(x) FIELD_PREP(QCA8K_PORT_HOL_CTRL0_EG_PRI5_BUF_MASK, x)
|
||||
+#define QCA8K_PORT_HOL_CTRL0_EG_PORT_BUF_MASK GENMASK(29, 24)
|
||||
+#define QCA8K_PORT_HOL_CTRL0_EG_PORT(x) FIELD_PREP(QCA8K_PORT_HOL_CTRL0_EG_PORT_BUF_MASK, x)
|
||||
|
||||
#define QCA8K_REG_PORT_HOL_CTRL1(_i) (0x974 + (_i) * 0x8)
|
||||
-#define QCA8K_PORT_HOL_CTRL1_ING_BUF GENMASK(3, 0)
|
||||
-#define QCA8K_PORT_HOL_CTRL1_ING(x) ((x) << 0)
|
||||
+#define QCA8K_PORT_HOL_CTRL1_ING_BUF_MASK GENMASK(3, 0)
|
||||
+#define QCA8K_PORT_HOL_CTRL1_ING(x) FIELD_PREP(QCA8K_PORT_HOL_CTRL1_ING_BUF_MASK, x)
|
||||
#define QCA8K_PORT_HOL_CTRL1_EG_PRI_BUF_EN BIT(6)
|
||||
#define QCA8K_PORT_HOL_CTRL1_EG_PORT_BUF_EN BIT(7)
|
||||
#define QCA8K_PORT_HOL_CTRL1_WRED_EN BIT(8)
|
||||
#define QCA8K_PORT_HOL_CTRL1_EG_MIRROR_EN BIT(16)
|
||||
|
||||
/* Pkt edit registers */
|
||||
+#define QCA8K_EGREES_VLAN_PORT_SHIFT(_i) (16 * ((_i) % 2))
|
||||
+#define QCA8K_EGREES_VLAN_PORT_MASK(_i) (GENMASK(11, 0) << QCA8K_EGREES_VLAN_PORT_SHIFT(_i))
|
||||
+#define QCA8K_EGREES_VLAN_PORT(_i, x) ((x) << QCA8K_EGREES_VLAN_PORT_SHIFT(_i))
|
||||
#define QCA8K_EGRESS_VLAN(x) (0x0c70 + (4 * (x / 2)))
|
||||
|
||||
/* L3 registers */
|
@ -0,0 +1,25 @@
|
||||
From 994c28b6f971fa5db8ae977daea37eee87d93d51 Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Mon, 22 Nov 2021 16:23:42 +0100
|
||||
Subject: net: dsa: qca8k: remove extra mutex_init in qca8k_setup
|
||||
|
||||
Mutex is already init in sw_probe. Remove the extra init in qca8k_setup.
|
||||
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/qca8k.c | 2 --
|
||||
1 file changed, 2 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/qca8k.c
|
||||
+++ b/drivers/net/dsa/qca8k.c
|
||||
@@ -1086,8 +1086,6 @@ qca8k_setup(struct dsa_switch *ds)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
- mutex_init(&priv->reg_mutex);
|
||||
-
|
||||
/* Start by setting up the register mapping */
|
||||
priv->regmap = devm_regmap_init(ds->dev, NULL, priv,
|
||||
&qca8k_regmap_config);
|
@ -0,0 +1,46 @@
|
||||
From 36b8af12f424e7a7f60a935c60a0fd4aa0822378 Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Mon, 22 Nov 2021 16:23:43 +0100
|
||||
Subject: net: dsa: qca8k: move regmap init in probe and set it mandatory
|
||||
|
||||
In preparation for regmap conversion, move regmap init in the probe
|
||||
function and make it mandatory as any read/write/rmw operation will be
|
||||
converted to regmap API.
|
||||
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/qca8k.c | 14 ++++++++------
|
||||
1 file changed, 8 insertions(+), 6 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/qca8k.c
|
||||
+++ b/drivers/net/dsa/qca8k.c
|
||||
@@ -1086,12 +1086,6 @@ qca8k_setup(struct dsa_switch *ds)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
- /* Start by setting up the register mapping */
|
||||
- priv->regmap = devm_regmap_init(ds->dev, NULL, priv,
|
||||
- &qca8k_regmap_config);
|
||||
- if (IS_ERR(priv->regmap))
|
||||
- dev_warn(priv->dev, "regmap initialization failed");
|
||||
-
|
||||
ret = qca8k_setup_mdio_bus(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -2085,6 +2079,14 @@ qca8k_sw_probe(struct mdio_device *mdiod
|
||||
gpiod_set_value_cansleep(priv->reset_gpio, 0);
|
||||
}
|
||||
|
||||
+ /* Start by setting up the register mapping */
|
||||
+ priv->regmap = devm_regmap_init(&mdiodev->dev, NULL, priv,
|
||||
+ &qca8k_regmap_config);
|
||||
+ if (IS_ERR(priv->regmap)) {
|
||||
+ dev_err(priv->dev, "regmap initialization failed");
|
||||
+ return PTR_ERR(priv->regmap);
|
||||
+ }
|
||||
+
|
||||
/* Check the detected switch id */
|
||||
ret = qca8k_read_switch_id(priv);
|
||||
if (ret)
|
@ -0,0 +1,249 @@
|
||||
From 8b5f3f29a81a71934d004e21a1292c1148b05926 Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Mon, 22 Nov 2021 16:23:44 +0100
|
||||
Subject: 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: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/qca8k.c | 107 +++++++++++++++++++++---------------------------
|
||||
1 file changed, 47 insertions(+), 60 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/qca8k.c
|
||||
+++ b/drivers/net/dsa/qca8k.c
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <linux/phy.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/bitfield.h>
|
||||
+#include <linux/regmap.h>
|
||||
#include <net/dsa.h>
|
||||
#include <linux/of_net.h>
|
||||
#include <linux/of_mdio.h>
|
||||
@@ -152,6 +153,25 @@ qca8k_set_page(struct mii_bus *bus, u16
|
||||
static int
|
||||
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;
|
||||
u16 r1, r2, page;
|
||||
int ret;
|
||||
@@ -172,8 +192,9 @@ exit:
|
||||
}
|
||||
|
||||
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;
|
||||
u16 r1, r2, page;
|
||||
int ret;
|
||||
@@ -194,8 +215,9 @@ exit:
|
||||
}
|
||||
|
||||
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;
|
||||
u16 r1, r2, page;
|
||||
u32 val;
|
||||
@@ -223,34 +245,6 @@ exit:
|
||||
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[] = {
|
||||
regmap_reg_range(0x0000, 0x00e4), /* Global control */
|
||||
regmap_reg_range(0x0100, 0x0168), /* EEE control */
|
||||
@@ -282,26 +276,19 @@ static struct regmap_config qca8k_regmap
|
||||
.max_register = 0x16ac, /* end MIB - Port6 range */
|
||||
.reg_read = qca8k_regmap_read,
|
||||
.reg_write = qca8k_regmap_write,
|
||||
+ .reg_update_bits = qca8k_regmap_update_bits,
|
||||
.rd_table = &qca8k_readable_table,
|
||||
+ .disable_locking = true, /* Locking is handled by qca8k read/write */
|
||||
+ .cache_type = REGCACHE_NONE, /* Explicitly disable CACHE */
|
||||
};
|
||||
|
||||
static int
|
||||
qca8k_busy_wait(struct qca8k_priv *priv, u32 reg, u32 mask)
|
||||
{
|
||||
- int ret, ret1;
|
||||
u32 val;
|
||||
|
||||
- ret = read_poll_timeout(qca8k_read, ret1, !(val & mask),
|
||||
- 0, QCA8K_BUSY_WAIT_TIMEOUT * USEC_PER_MSEC, false,
|
||||
- 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;
|
||||
+ return regmap_read_poll_timeout(priv->regmap, reg, val, !(val & mask), 0,
|
||||
+ QCA8K_BUSY_WAIT_TIMEOUT * USEC_PER_MSEC);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -568,7 +555,7 @@ qca8k_mib_init(struct qca8k_priv *priv)
|
||||
int ret;
|
||||
|
||||
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)
|
||||
goto exit;
|
||||
|
||||
@@ -576,7 +563,7 @@ qca8k_mib_init(struct qca8k_priv *priv)
|
||||
if (ret)
|
||||
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)
|
||||
goto exit;
|
||||
|
||||
@@ -597,9 +584,9 @@ qca8k_port_set_status(struct qca8k_priv
|
||||
mask |= QCA8K_PORT_STATUS_LINK_AUTO;
|
||||
|
||||
if (enable)
|
||||
- qca8k_reg_set(priv, QCA8K_REG_PORT_STATUS(port), mask);
|
||||
+ regmap_set_bits(priv->regmap, QCA8K_REG_PORT_STATUS(port), mask);
|
||||
else
|
||||
- qca8k_reg_clear(priv, QCA8K_REG_PORT_STATUS(port), mask);
|
||||
+ regmap_clear_bits(priv->regmap, QCA8K_REG_PORT_STATUS(port), mask);
|
||||
}
|
||||
|
||||
static u32
|
||||
@@ -861,8 +848,8 @@ qca8k_setup_mdio_bus(struct qca8k_priv *
|
||||
* a dt-overlay and driver reload changed the configuration
|
||||
*/
|
||||
|
||||
- return qca8k_reg_clear(priv, QCA8K_MDIO_MASTER_CTRL,
|
||||
- QCA8K_MDIO_MASTER_EN);
|
||||
+ return regmap_clear_bits(priv->regmap, QCA8K_MDIO_MASTER_CTRL,
|
||||
+ QCA8K_MDIO_MASTER_EN);
|
||||
}
|
||||
|
||||
/* Check if the devicetree declare the port:phy mapping */
|
||||
@@ -1099,16 +1086,16 @@ qca8k_setup(struct dsa_switch *ds)
|
||||
return ret;
|
||||
|
||||
/* Make sure MAC06 is disabled */
|
||||
- ret = qca8k_reg_clear(priv, QCA8K_REG_PORT0_PAD_CTRL,
|
||||
- QCA8K_PORT0_PAD_MAC06_EXCHANGE_EN);
|
||||
+ ret = regmap_clear_bits(priv->regmap, QCA8K_REG_PORT0_PAD_CTRL,
|
||||
+ QCA8K_PORT0_PAD_MAC06_EXCHANGE_EN);
|
||||
if (ret) {
|
||||
dev_err(priv->dev, "failed disabling MAC06 exchange");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Enable CPU Port */
|
||||
- ret = qca8k_reg_set(priv, QCA8K_REG_GLOBAL_FW_CTRL0,
|
||||
- QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN);
|
||||
+ ret = regmap_set_bits(priv->regmap, QCA8K_REG_GLOBAL_FW_CTRL0,
|
||||
+ QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN);
|
||||
if (ret) {
|
||||
dev_err(priv->dev, "failed enabling CPU port");
|
||||
return ret;
|
||||
@@ -1176,8 +1163,8 @@ qca8k_setup(struct dsa_switch *ds)
|
||||
return ret;
|
||||
|
||||
/* Enable ARP Auto-learning by default */
|
||||
- ret = qca8k_reg_set(priv, QCA8K_PORT_LOOKUP_CTRL(i),
|
||||
- QCA8K_PORT_LOOKUP_LEARN);
|
||||
+ ret = regmap_set_bits(priv->regmap, QCA8K_PORT_LOOKUP_CTRL(i),
|
||||
+ QCA8K_PORT_LOOKUP_LEARN);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -1745,9 +1732,9 @@ qca8k_port_bridge_join(struct dsa_switch
|
||||
/* Add this port to the portvlan mask of the other ports
|
||||
* in the bridge
|
||||
*/
|
||||
- ret = qca8k_reg_set(priv,
|
||||
- QCA8K_PORT_LOOKUP_CTRL(i),
|
||||
- BIT(port));
|
||||
+ ret = regmap_set_bits(priv->regmap,
|
||||
+ QCA8K_PORT_LOOKUP_CTRL(i),
|
||||
+ BIT(port));
|
||||
if (ret)
|
||||
return ret;
|
||||
if (i != port)
|
||||
@@ -1777,9 +1764,9 @@ qca8k_port_bridge_leave(struct dsa_switc
|
||||
/* Remove this port to the portvlan mask of the other ports
|
||||
* in the bridge
|
||||
*/
|
||||
- qca8k_reg_clear(priv,
|
||||
- QCA8K_PORT_LOOKUP_CTRL(i),
|
||||
- BIT(port));
|
||||
+ regmap_clear_bits(priv->regmap,
|
||||
+ QCA8K_PORT_LOOKUP_CTRL(i),
|
||||
+ BIT(port));
|
||||
}
|
||||
|
||||
/* Set the cpu port to be the only one in the portvlan mask of
|
@ -0,0 +1,120 @@
|
||||
From c126f118b330ccf0db0dda4a4bd6c729865a205f Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Mon, 22 Nov 2021 16:23:45 +0100
|
||||
Subject: net: dsa: qca8k: add additional MIB counter and make it dynamic
|
||||
|
||||
We are currently missing 2 additionals MIB counter present in QCA833x
|
||||
switch.
|
||||
QC832x switch have 39 MIB counter and QCA833X have 41 MIB counter.
|
||||
Add the additional MIB counter and rework the MIB function to print the
|
||||
correct supported counter from the match_data struct.
|
||||
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/qca8k.c | 23 ++++++++++++++++++++---
|
||||
drivers/net/dsa/qca8k.h | 4 ++++
|
||||
2 files changed, 24 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/qca8k.c
|
||||
+++ b/drivers/net/dsa/qca8k.c
|
||||
@@ -70,6 +70,8 @@ static const struct qca8k_mib_desc ar832
|
||||
MIB_DESC(1, 0x9c, "TxExcDefer"),
|
||||
MIB_DESC(1, 0xa0, "TxDefer"),
|
||||
MIB_DESC(1, 0xa4, "TxLateCol"),
|
||||
+ MIB_DESC(1, 0xa8, "RXUnicast"),
|
||||
+ MIB_DESC(1, 0xac, "TXUnicast"),
|
||||
};
|
||||
|
||||
/* The 32bit switch registers are accessed indirectly. To achieve this we need
|
||||
@@ -1605,12 +1607,16 @@ qca8k_phylink_mac_link_up(struct dsa_swi
|
||||
static void
|
||||
qca8k_get_strings(struct dsa_switch *ds, int port, u32 stringset, uint8_t *data)
|
||||
{
|
||||
+ const struct qca8k_match_data *match_data;
|
||||
+ struct qca8k_priv *priv = ds->priv;
|
||||
int i;
|
||||
|
||||
if (stringset != ETH_SS_STATS)
|
||||
return;
|
||||
|
||||
- for (i = 0; i < ARRAY_SIZE(ar8327_mib); i++)
|
||||
+ match_data = of_device_get_match_data(priv->dev);
|
||||
+
|
||||
+ for (i = 0; i < match_data->mib_count; i++)
|
||||
strncpy(data + i * ETH_GSTRING_LEN, ar8327_mib[i].name,
|
||||
ETH_GSTRING_LEN);
|
||||
}
|
||||
@@ -1620,12 +1626,15 @@ qca8k_get_ethtool_stats(struct dsa_switc
|
||||
uint64_t *data)
|
||||
{
|
||||
struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
|
||||
+ const struct qca8k_match_data *match_data;
|
||||
const struct qca8k_mib_desc *mib;
|
||||
u32 reg, i, val;
|
||||
u32 hi = 0;
|
||||
int ret;
|
||||
|
||||
- for (i = 0; i < ARRAY_SIZE(ar8327_mib); i++) {
|
||||
+ match_data = of_device_get_match_data(priv->dev);
|
||||
+
|
||||
+ for (i = 0; i < match_data->mib_count; i++) {
|
||||
mib = &ar8327_mib[i];
|
||||
reg = QCA8K_PORT_MIB_COUNTER(port) + mib->offset;
|
||||
|
||||
@@ -1648,10 +1657,15 @@ qca8k_get_ethtool_stats(struct dsa_switc
|
||||
static int
|
||||
qca8k_get_sset_count(struct dsa_switch *ds, int port, int sset)
|
||||
{
|
||||
+ const struct qca8k_match_data *match_data;
|
||||
+ struct qca8k_priv *priv = ds->priv;
|
||||
+
|
||||
if (sset != ETH_SS_STATS)
|
||||
return 0;
|
||||
|
||||
- return ARRAY_SIZE(ar8327_mib);
|
||||
+ match_data = of_device_get_match_data(priv->dev);
|
||||
+
|
||||
+ return match_data->mib_count;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -2146,14 +2160,17 @@ static SIMPLE_DEV_PM_OPS(qca8k_pm_ops,
|
||||
static const struct qca8k_match_data qca8327 = {
|
||||
.id = QCA8K_ID_QCA8327,
|
||||
.reduced_package = true,
|
||||
+ .mib_count = QCA8K_QCA832X_MIB_COUNT,
|
||||
};
|
||||
|
||||
static const struct qca8k_match_data qca8328 = {
|
||||
.id = QCA8K_ID_QCA8327,
|
||||
+ .mib_count = QCA8K_QCA832X_MIB_COUNT,
|
||||
};
|
||||
|
||||
static const struct qca8k_match_data qca833x = {
|
||||
.id = QCA8K_ID_QCA8337,
|
||||
+ .mib_count = QCA8K_QCA833X_MIB_COUNT,
|
||||
};
|
||||
|
||||
static const struct of_device_id qca8k_of_match[] = {
|
||||
--- a/drivers/net/dsa/qca8k.h
|
||||
+++ b/drivers/net/dsa/qca8k.h
|
||||
@@ -21,6 +21,9 @@
|
||||
#define PHY_ID_QCA8337 0x004dd036
|
||||
#define QCA8K_ID_QCA8337 0x13
|
||||
|
||||
+#define QCA8K_QCA832X_MIB_COUNT 39
|
||||
+#define QCA8K_QCA833X_MIB_COUNT 41
|
||||
+
|
||||
#define QCA8K_BUSY_WAIT_TIMEOUT 2000
|
||||
|
||||
#define QCA8K_NUM_FDB_RECORDS 2048
|
||||
@@ -279,6 +282,7 @@ struct ar8xxx_port_status {
|
||||
struct qca8k_match_data {
|
||||
u8 id;
|
||||
bool reduced_package;
|
||||
+ u8 mib_count;
|
||||
};
|
||||
|
||||
enum {
|
@ -0,0 +1,53 @@
|
||||
From 4592538bfb0d5d3c3c8a1d7071724d081412ac91 Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Mon, 22 Nov 2021 16:23:46 +0100
|
||||
Subject: net: dsa: qca8k: add support for port fast aging
|
||||
|
||||
The switch supports fast aging by flushing any rule in the ARL
|
||||
table for a specific port.
|
||||
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/qca8k.c | 11 +++++++++++
|
||||
drivers/net/dsa/qca8k.h | 1 +
|
||||
2 files changed, 12 insertions(+)
|
||||
|
||||
--- a/drivers/net/dsa/qca8k.c
|
||||
+++ b/drivers/net/dsa/qca8k.c
|
||||
@@ -1790,6 +1790,16 @@ qca8k_port_bridge_leave(struct dsa_switc
|
||||
QCA8K_PORT_LOOKUP_MEMBER, BIT(cpu_port));
|
||||
}
|
||||
|
||||
+static void
|
||||
+qca8k_port_fast_age(struct dsa_switch *ds, int port)
|
||||
+{
|
||||
+ struct qca8k_priv *priv = ds->priv;
|
||||
+
|
||||
+ mutex_lock(&priv->reg_mutex);
|
||||
+ qca8k_fdb_access(priv, QCA8K_FDB_FLUSH_PORT, port);
|
||||
+ mutex_unlock(&priv->reg_mutex);
|
||||
+}
|
||||
+
|
||||
static int
|
||||
qca8k_port_enable(struct dsa_switch *ds, int port,
|
||||
struct phy_device *phy)
|
||||
@@ -2005,6 +2015,7 @@ static const struct dsa_switch_ops qca8k
|
||||
.port_stp_state_set = qca8k_port_stp_state_set,
|
||||
.port_bridge_join = qca8k_port_bridge_join,
|
||||
.port_bridge_leave = qca8k_port_bridge_leave,
|
||||
+ .port_fast_age = qca8k_port_fast_age,
|
||||
.port_fdb_add = qca8k_port_fdb_add,
|
||||
.port_fdb_del = qca8k_port_fdb_del,
|
||||
.port_fdb_dump = qca8k_port_fdb_dump,
|
||||
--- a/drivers/net/dsa/qca8k.h
|
||||
+++ b/drivers/net/dsa/qca8k.h
|
||||
@@ -262,6 +262,7 @@ enum qca8k_fdb_cmd {
|
||||
QCA8K_FDB_FLUSH = 1,
|
||||
QCA8K_FDB_LOAD = 2,
|
||||
QCA8K_FDB_PURGE = 3,
|
||||
+ QCA8K_FDB_FLUSH_PORT = 5,
|
||||
QCA8K_FDB_NEXT = 6,
|
||||
QCA8K_FDB_SEARCH = 7,
|
||||
};
|
@ -0,0 +1,78 @@
|
||||
From 6a3bdc5209f45d2af83aa92433ab6e5cf2297aa4 Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Mon, 22 Nov 2021 16:23:47 +0100
|
||||
Subject: net: dsa: qca8k: add set_ageing_time support
|
||||
|
||||
qca8k support setting ageing time in step of 7s. Add support for it and
|
||||
set the max value accepted of 7645m.
|
||||
Documentation talks about support for 10000m but that values doesn't
|
||||
make sense as the value doesn't match the max value in the reg.
|
||||
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/qca8k.c | 25 +++++++++++++++++++++++++
|
||||
drivers/net/dsa/qca8k.h | 3 +++
|
||||
2 files changed, 28 insertions(+)
|
||||
|
||||
--- a/drivers/net/dsa/qca8k.c
|
||||
+++ b/drivers/net/dsa/qca8k.c
|
||||
@@ -1261,6 +1261,10 @@ qca8k_setup(struct dsa_switch *ds)
|
||||
/* We don't have interrupts for link changes, so we need to poll */
|
||||
ds->pcs_poll = true;
|
||||
|
||||
+ /* Set min a max ageing value supported */
|
||||
+ ds->ageing_time_min = 7000;
|
||||
+ ds->ageing_time_max = 458745000;
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1801,6 +1805,26 @@ qca8k_port_fast_age(struct dsa_switch *d
|
||||
}
|
||||
|
||||
static int
|
||||
+qca8k_set_ageing_time(struct dsa_switch *ds, unsigned int msecs)
|
||||
+{
|
||||
+ struct qca8k_priv *priv = ds->priv;
|
||||
+ unsigned int secs = msecs / 1000;
|
||||
+ u32 val;
|
||||
+
|
||||
+ /* AGE_TIME reg is set in 7s step */
|
||||
+ val = secs / 7;
|
||||
+
|
||||
+ /* Handle case with 0 as val to NOT disable
|
||||
+ * learning
|
||||
+ */
|
||||
+ if (!val)
|
||||
+ val = 1;
|
||||
+
|
||||
+ return regmap_update_bits(priv->regmap, QCA8K_REG_ATU_CTRL, QCA8K_ATU_AGE_TIME_MASK,
|
||||
+ QCA8K_ATU_AGE_TIME(val));
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
qca8k_port_enable(struct dsa_switch *ds, int port,
|
||||
struct phy_device *phy)
|
||||
{
|
||||
@@ -2006,6 +2030,7 @@ static const struct dsa_switch_ops qca8k
|
||||
.get_strings = qca8k_get_strings,
|
||||
.get_ethtool_stats = qca8k_get_ethtool_stats,
|
||||
.get_sset_count = qca8k_get_sset_count,
|
||||
+ .set_ageing_time = qca8k_set_ageing_time,
|
||||
.get_mac_eee = qca8k_get_mac_eee,
|
||||
.set_mac_eee = qca8k_set_mac_eee,
|
||||
.port_enable = qca8k_port_enable,
|
||||
--- a/drivers/net/dsa/qca8k.h
|
||||
+++ b/drivers/net/dsa/qca8k.h
|
||||
@@ -175,6 +175,9 @@
|
||||
#define QCA8K_VTU_FUNC1_BUSY BIT(31)
|
||||
#define QCA8K_VTU_FUNC1_VID_MASK GENMASK(27, 16)
|
||||
#define QCA8K_VTU_FUNC1_FULL BIT(4)
|
||||
+#define QCA8K_REG_ATU_CTRL 0x618
|
||||
+#define QCA8K_ATU_AGE_TIME_MASK GENMASK(15, 0)
|
||||
+#define QCA8K_ATU_AGE_TIME(x) FIELD_PREP(QCA8K_ATU_AGE_TIME_MASK, (x))
|
||||
#define QCA8K_REG_GLOBAL_FW_CTRL0 0x620
|
||||
#define QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN BIT(10)
|
||||
#define QCA8K_REG_GLOBAL_FW_CTRL1 0x624
|
@ -0,0 +1,142 @@
|
||||
From ba8f870dfa635113ce6e8095a5eb1835ecde2e9e Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Mon, 22 Nov 2021 16:23:48 +0100
|
||||
Subject: net: dsa: qca8k: add support for mdb_add/del
|
||||
|
||||
Add support for mdb add/del function. The ARL table is used to insert
|
||||
the rule. The rule will be searched, deleted and reinserted with the
|
||||
port mask updated. The function will check if the rule has to be updated
|
||||
or insert directly with no deletion of the old rule.
|
||||
If every port is removed from the port mask, the rule is removed.
|
||||
The rule is set STATIC in the ARL table (aka it doesn't age) to not be
|
||||
flushed by fast age function.
|
||||
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/qca8k.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 99 insertions(+)
|
||||
|
||||
--- a/drivers/net/dsa/qca8k.c
|
||||
+++ b/drivers/net/dsa/qca8k.c
|
||||
@@ -436,6 +436,81 @@ qca8k_fdb_flush(struct qca8k_priv *priv)
|
||||
}
|
||||
|
||||
static int
|
||||
+qca8k_fdb_search_and_insert(struct qca8k_priv *priv, u8 port_mask,
|
||||
+ const u8 *mac, u16 vid)
|
||||
+{
|
||||
+ struct qca8k_fdb fdb = { 0 };
|
||||
+ int ret;
|
||||
+
|
||||
+ mutex_lock(&priv->reg_mutex);
|
||||
+
|
||||
+ qca8k_fdb_write(priv, vid, 0, mac, 0);
|
||||
+ ret = qca8k_fdb_access(priv, QCA8K_FDB_SEARCH, -1);
|
||||
+ if (ret < 0)
|
||||
+ goto exit;
|
||||
+
|
||||
+ ret = qca8k_fdb_read(priv, &fdb);
|
||||
+ if (ret < 0)
|
||||
+ goto exit;
|
||||
+
|
||||
+ /* Rule exist. Delete first */
|
||||
+ if (!fdb.aging) {
|
||||
+ ret = qca8k_fdb_access(priv, QCA8K_FDB_PURGE, -1);
|
||||
+ if (ret)
|
||||
+ goto exit;
|
||||
+ }
|
||||
+
|
||||
+ /* Add port to fdb portmask */
|
||||
+ fdb.port_mask |= port_mask;
|
||||
+
|
||||
+ qca8k_fdb_write(priv, vid, fdb.port_mask, mac, fdb.aging);
|
||||
+ ret = qca8k_fdb_access(priv, QCA8K_FDB_LOAD, -1);
|
||||
+
|
||||
+exit:
|
||||
+ mutex_unlock(&priv->reg_mutex);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+qca8k_fdb_search_and_del(struct qca8k_priv *priv, u8 port_mask,
|
||||
+ const u8 *mac, u16 vid)
|
||||
+{
|
||||
+ struct qca8k_fdb fdb = { 0 };
|
||||
+ int ret;
|
||||
+
|
||||
+ mutex_lock(&priv->reg_mutex);
|
||||
+
|
||||
+ qca8k_fdb_write(priv, vid, 0, mac, 0);
|
||||
+ ret = qca8k_fdb_access(priv, QCA8K_FDB_SEARCH, -1);
|
||||
+ if (ret < 0)
|
||||
+ goto exit;
|
||||
+
|
||||
+ /* Rule doesn't exist. Why delete? */
|
||||
+ if (!fdb.aging) {
|
||||
+ ret = -EINVAL;
|
||||
+ goto exit;
|
||||
+ }
|
||||
+
|
||||
+ ret = qca8k_fdb_access(priv, QCA8K_FDB_PURGE, -1);
|
||||
+ if (ret)
|
||||
+ goto exit;
|
||||
+
|
||||
+ /* Only port in the rule is this port. Don't re insert */
|
||||
+ if (fdb.port_mask == port_mask)
|
||||
+ goto exit;
|
||||
+
|
||||
+ /* Remove port from port mask */
|
||||
+ fdb.port_mask &= ~port_mask;
|
||||
+
|
||||
+ qca8k_fdb_write(priv, vid, fdb.port_mask, mac, fdb.aging);
|
||||
+ ret = qca8k_fdb_access(priv, QCA8K_FDB_LOAD, -1);
|
||||
+
|
||||
+exit:
|
||||
+ mutex_unlock(&priv->reg_mutex);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
qca8k_vlan_access(struct qca8k_priv *priv, enum qca8k_vlan_cmd cmd, u16 vid)
|
||||
{
|
||||
u32 reg;
|
||||
@@ -1929,6 +2004,28 @@ qca8k_port_fdb_dump(struct dsa_switch *d
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static void
|
||||
+qca8k_port_mdb_add(struct dsa_switch *ds, int port,
|
||||
+ const struct switchdev_obj_port_mdb *mdb)
|
||||
+{
|
||||
+ struct qca8k_priv *priv = ds->priv;
|
||||
+ const u8 *addr = mdb->addr;
|
||||
+ u16 vid = mdb->vid;
|
||||
+
|
||||
+ qca8k_fdb_search_and_insert(priv, BIT(port), addr, vid);
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+qca8k_port_mdb_del(struct dsa_switch *ds, int port,
|
||||
+ const struct switchdev_obj_port_mdb *mdb)
|
||||
+{
|
||||
+ struct qca8k_priv *priv = ds->priv;
|
||||
+ const u8 *addr = mdb->addr;
|
||||
+ u16 vid = mdb->vid;
|
||||
+
|
||||
+ return qca8k_fdb_search_and_del(priv, BIT(port), addr, vid);
|
||||
+}
|
||||
+
|
||||
static int
|
||||
qca8k_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering,
|
||||
struct switchdev_trans *trans)
|
||||
@@ -2044,6 +2141,8 @@ static const struct dsa_switch_ops qca8k
|
||||
.port_fdb_add = qca8k_port_fdb_add,
|
||||
.port_fdb_del = qca8k_port_fdb_del,
|
||||
.port_fdb_dump = qca8k_port_fdb_dump,
|
||||
+ .port_mdb_add = qca8k_port_mdb_add,
|
||||
+ .port_mdb_del = qca8k_port_mdb_del,
|
||||
.port_vlan_filtering = qca8k_port_vlan_filtering,
|
||||
.port_vlan_prepare = qca8k_port_vlan_prepare,
|
||||
.port_vlan_add = qca8k_port_vlan_add,
|
@ -116,7 +116,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/property.h>
|
||||
@@ -3296,3 +3297,5 @@ static int __init regmap_initcall(void)
|
||||
@@ -3297,3 +3298,5 @@ static int __init regmap_initcall(void)
|
||||
return 0;
|
||||
}
|
||||
postcore_initcall(regmap_initcall);
|
||||
|
Loading…
Reference in New Issue
Block a user