ag71xx: allow setting port state and storm control registers
authorYousong Zhou <yszhou4tech@gmail.com>
Fri, 6 Jul 2018 06:28:06 +0000 (14:28 +0800)
committerYousong Zhou <yszhou4tech@gmail.com>
Fri, 6 Jul 2018 06:28:06 +0000 (14:28 +0800)
Signed-off-by: Yousong Zhou <yszhou4tech@gmail.com>
target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_ar7240.c

index 3f2f64e2aef80075b8ca804af1cb90d248b913f7..3d5d55df5868a265048e34ba2452badfcd603203 100644 (file)
 #define AR7240_PORT_CTRL_MIRROR_TX     BIT(16)
 #define AR7240_PORT_CTRL_MIRROR_RX     BIT(17)
 
+#define AR7240_REG_PORT_STORM_CTRL(_port)      (AR7240_REG_PORT_BASE((_port)) + 0x14)
+#define AR7240_STORM_CTRL_RES_M        ((BITM(21) << 11) | (BITM(4) << 4))
+#define AR7240_STORM_CTRL_STORM_RATE_M BITM(4)
+#define AR7240_STORM_CTRL_STORM_RATE_MAX       0xb
+
 #define AR7240_REG_PORT_VLAN(_port)    (AR7240_REG_PORT_BASE((_port)) + 0x08)
 
 #define AR7240_PORT_VLAN_DEFAULT_ID_S  0
@@ -1161,6 +1166,72 @@ static struct switch_attr ar7240_globals[] = {
        },
 };
 
+static int ar7240_get_port_state(struct switch_dev *dev,
+                                   const struct switch_attr *attr,
+                                   struct switch_val *val)
+{
+       struct ar7240sw *as = sw_to_ar7240(dev);
+       struct mii_bus *mii = as->mii_bus;
+       u32 state;
+
+       if (val->port_vlan > AR7240_NUM_PORTS)
+               return -EINVAL;
+
+       state = ar7240sw_reg_read(mii, AR7240_REG_PORT_CTRL(val->port_vlan));
+       val->value.i = state & AR7240_PORT_CTRL_STATE_M;
+       return 0;
+}
+
+static int ar7240_set_port_state(struct switch_dev *dev,
+                                   const struct switch_attr *attr,
+                                   struct switch_val *val)
+{
+       struct ar7240sw *as = sw_to_ar7240(dev);
+       struct mii_bus *mii = as->mii_bus;
+
+       if (val->port_vlan > AR7240_NUM_PORTS)
+               return -EINVAL;
+
+       ar7240sw_reg_rmw(mii, AR7240_REG_PORT_CTRL(val->port_vlan),
+                       AR7240_PORT_CTRL_STATE_M, val->value.i);
+       return 0;
+}
+
+static int ar7240_get_port_storm_ctrl(struct switch_dev *dev,
+                                   const struct switch_attr *attr,
+                                   struct switch_val *val)
+{
+       struct ar7240sw *as = sw_to_ar7240(dev);
+       struct mii_bus *mii = as->mii_bus;
+
+       if (val->port_vlan > AR7240_NUM_PORTS)
+               return -EINVAL;
+
+       val->value.i = ar7240sw_reg_read(mii, AR7240_REG_PORT_STORM_CTRL(val->port_vlan));
+       return 0;
+}
+
+static int ar7240_set_port_storm_ctrl(struct switch_dev *dev,
+                                   const struct switch_attr *attr,
+                                   struct switch_val *val)
+{
+       struct ar7240sw *as = sw_to_ar7240(dev);
+       struct mii_bus *mii = as->mii_bus;
+       u32 i;
+
+       if (val->port_vlan > AR7240_NUM_PORTS)
+               return -EINVAL;
+
+       i = val->value.i;
+       if (i & AR7240_STORM_CTRL_RES_M)
+               return -EINVAL;
+       if ((i & AR7240_STORM_CTRL_STORM_RATE_M) > AR7240_STORM_CTRL_STORM_RATE_MAX)
+               return -EINVAL;
+
+       ar7240sw_reg_write(mii, AR7240_REG_PORT_STORM_CTRL(val->port_vlan), i);
+       return 0;
+}
+
 static struct switch_attr ar7240_port[] = {
        {
                .type = SWITCH_TYPE_INT,
@@ -1177,6 +1248,19 @@ static struct switch_attr ar7240_port[] = {
                .set = ar7240_set_mirror_tx,
                .get = ar7240_get_mirror_tx,
                .max = 1
+       }, {
+               .name = "state",
+               .description = "Get/Set port state",
+               .max = 1,
+               .set = ar7240_set_port_state,
+               .get = ar7240_get_port_state,
+       }, {
+               .type = SWITCH_TYPE_INT,
+               .name = "storm_ctrl",
+               .description = "Get/Set port storm control registers",
+               .max = 1,
+               .set = ar7240_set_port_storm_ctrl,
+               .get = ar7240_get_port_storm_ctrl,
        },
 };