+static int
+adm6996_get_port_link(struct switch_dev *dev, int port,
+ struct switch_port_link *link)
+{
+ struct adm6996_priv *priv = to_adm(dev);
+
+ u16 reg = 0;
+ u32 speed;
+
+ if (port >= ADM_NUM_PORTS)
+ return -EINVAL;
+
+ switch (port) {
+ case 0:
+ reg = r16(priv, ADM_PS0);
+ break;
+ case 1:
+ reg = r16(priv, ADM_PS0);
+ reg = reg >> 8;
+ break;
+ case 2:
+ reg = r16(priv, ADM_PS1);
+ break;
+ case 3:
+ reg = r16(priv, ADM_PS1);
+ reg = reg >> 8;
+ break;
+ case 4:
+ reg = r16(priv, ADM_PS1);
+ reg = reg >> 12;
+ break;
+ case 5:
+ reg = r16(priv, ADM_PS2);
+ /* Bits 0, 1, 3 and 4. */
+ reg = (reg & 3) | ((reg & 24) >> 1);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ link->link = reg & ADM_PS_LS;
+ if (!link->link)
+ return 0;
+ link->aneg = true;
+ link->duplex = reg & ADM_PS_DS;
+ link->tx_flow = reg & ADM_PS_FCS;
+ link->rx_flow = reg & ADM_PS_FCS;
+ if (reg & ADM_PS_SS)
+ link->speed = SWITCH_PORT_SPEED_100;
+ else
+ link->speed = SWITCH_PORT_SPEED_10;
+
+ return 0;
+}
+
+static int
+adm6996_sw_get_port_mib(struct switch_dev *dev,
+ const struct switch_attr *attr,
+ struct switch_val *val)
+{
+ struct adm6996_priv *priv = to_adm(dev);
+ int port;
+ char *buf = priv->buf;
+ int i, len = 0;
+ u32 reg = 0;
+
+ port = val->port_vlan;
+ if (port >= ADM_NUM_PORTS)
+ return -EINVAL;
+
+ mutex_lock(&priv->mib_lock);
+
+ len += snprintf(buf + len, sizeof(priv->buf) - len,
+ "Port %d MIB counters\n",
+ port);
+
+ for (i = 0; i < ARRAY_SIZE(adm6996_mibs); i++) {
+ reg = r16(priv, adm6996_mibs[i].offset + ADM_OFFSET_PORT(port));
+ reg += r16(priv, adm6996_mibs[i].offset + ADM_OFFSET_PORT(port) + 1) << 16;
+ len += snprintf(buf + len, sizeof(priv->buf) - len,
+ "%-12s: %lu\n",
+ adm6996_mibs[i].name,
+ reg);
+ }
+
+ mutex_unlock(&priv->mib_lock);
+
+ val->value.s = buf;
+ val->len = len;
+
+ return 0;
+}
+