kernel: set and get ports speed for rtl8367d family chips
authorMieczyslaw Nalewaj <namiltd@yahoo.com>
Fri, 23 Aug 2024 19:24:03 +0000 (21:24 +0200)
committerHauke Mehrtens <hauke@hauke-m.de>
Thu, 29 Aug 2024 18:50:01 +0000 (20:50 +0200)
Set and get ports speed for rtl8367d family chips

Co-authored-by: Serge Vasilugin <vasilugin@yandex.ru>
Signed-off-by: Mieczyslaw Nalewaj <namiltd@yahoo.com>
Link: https://github.com/openwrt/openwrt/pull/14804
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
target/linux/generic/files/drivers/net/phy/rtl8367b.c

index a80e1c2f80d965e9a6ec97f8a1963575954b35fb..a1efd8fe5bd91bd23c68441b55ad3c1c29a50e80 100644 (file)
@@ -268,6 +268,14 @@ struct rtl8367b_initval {
 #define RTL8367B_MIB_RXB_ID            0       /* IfInOctets */
 #define RTL8367B_MIB_TXB_ID            28      /* IfOutOctets */
 
+#define RTL8367D_PORT_STATUS_REG(_p)           (0x12d0 + (_p))
+
+#define RTL8367D_PORT_STATUS_SPEED1_MASK       0x3000
+#define RTL8367D_PORT_STATUS_SPEED1_SHIFT      10 /*12-2*/
+
+#define RTL8367D_REG_MAC0_FORCE_SELECT         0x12c0
+#define RTL8367D_REG_MAC0_FORCE_SELECT_EN      0x12c8
+
 static struct rtl8366_mib_counter
 rtl8367b_mib_counters[RTL8367B_NUM_MIB_COUNTERS] = {
        {0,   0, 4, "ifInOctets"                        },
@@ -646,23 +654,31 @@ static int rtl8367b_extif_set_force(struct rtl8366_smi *smi, int id,
        u32 val;
        int err;
 
-       mask = (RTL8367B_DI_FORCE_MODE |
-               RTL8367B_DI_FORCE_NWAY |
-               RTL8367B_DI_FORCE_TXPAUSE |
-               RTL8367B_DI_FORCE_RXPAUSE |
-               RTL8367B_DI_FORCE_LINK |
-               RTL8367B_DI_FORCE_DUPLEX |
-               RTL8367B_DI_FORCE_SPEED_MASK);
-
-       val = pa->speed;
-       val |= pa->force_mode ? RTL8367B_DI_FORCE_MODE : 0;
+       val = pa->speed & RTL8367B_DI_FORCE_SPEED_MASK;
        val |= pa->nway ? RTL8367B_DI_FORCE_NWAY : 0;
        val |= pa->txpause ? RTL8367B_DI_FORCE_TXPAUSE : 0;
        val |= pa->rxpause ? RTL8367B_DI_FORCE_RXPAUSE : 0;
        val |= pa->link ? RTL8367B_DI_FORCE_LINK : 0;
        val |= pa->duplex ? RTL8367B_DI_FORCE_DUPLEX : 0;
 
-       REG_RMW(smi, RTL8367B_DI_FORCE_REG(id), mask, val);
+       if (smi->rtl8367b_chip >= RTL8367B_CHIP_RTL8367S_VB) { /* Family D */
+               val |= (pa->speed << RTL8367D_PORT_STATUS_SPEED1_SHIFT) & RTL8367D_PORT_STATUS_SPEED1_MASK;
+               if (smi->cpu_port != UINT_MAX) {
+                       REG_WR(smi, RTL8367D_REG_MAC0_FORCE_SELECT + smi->cpu_port, val);
+                       REG_WR(smi, RTL8367D_REG_MAC0_FORCE_SELECT_EN + smi->cpu_port, pa->force_mode ? 0xffff : 0x0000);
+               }
+       } else {
+               val |= pa->force_mode ? RTL8367B_DI_FORCE_MODE : 0;
+               mask = (RTL8367B_DI_FORCE_MODE |
+                       RTL8367B_DI_FORCE_NWAY |
+                       RTL8367B_DI_FORCE_TXPAUSE |
+                       RTL8367B_DI_FORCE_RXPAUSE |
+                       RTL8367B_DI_FORCE_LINK |
+                       RTL8367B_DI_FORCE_DUPLEX |
+                       RTL8367B_DI_FORCE_SPEED_MASK);
+
+               REG_RMW(smi, RTL8367B_DI_FORCE_REG(id), mask, val);
+       }
 
        return 0;
 }
@@ -1100,7 +1116,10 @@ static int rtl8367b_sw_get_port_link(struct switch_dev *dev,
        if (port >= RTL8367B_NUM_PORTS)
                return -EINVAL;
 
-       rtl8366_smi_read_reg(smi, RTL8367B_PORT_STATUS_REG(port), &data);
+       if (smi->rtl8367b_chip >= RTL8367B_CHIP_RTL8367S_VB) /* Family D */
+               rtl8366_smi_read_reg(smi, RTL8367D_PORT_STATUS_REG(port), &data);
+       else
+               rtl8366_smi_read_reg(smi, RTL8367B_PORT_STATUS_REG(port), &data);
 
        link->link = !!(data & RTL8367B_PORT_STATUS_LINK);
        if (!link->link)
@@ -1111,15 +1130,18 @@ static int rtl8367b_sw_get_port_link(struct switch_dev *dev,
        link->tx_flow = !!(data & RTL8367B_PORT_STATUS_TXPAUSE);
        link->aneg = !!(data & RTL8367B_PORT_STATUS_NWAY);
 
-       speed = (data & RTL8367B_PORT_STATUS_SPEED_MASK);
+       if (smi->rtl8367b_chip >= RTL8367B_CHIP_RTL8367S_VB) /* Family D */
+               speed = (data & RTL8367B_PORT_STATUS_SPEED_MASK) | ((data & RTL8367D_PORT_STATUS_SPEED1_MASK) >> RTL8367D_PORT_STATUS_SPEED1_SHIFT);
+       else
+               speed = (data & RTL8367B_PORT_STATUS_SPEED_MASK);
        switch (speed) {
-       case 0:
+       case RTL8367B_PORT_STATUS_SPEED_10:
                link->speed = SWITCH_PORT_SPEED_10;
                break;
-       case 1:
+       case RTL8367B_PORT_STATUS_SPEED_100:
                link->speed = SWITCH_PORT_SPEED_100;
                break;
-       case 2:
+       case RTL8367B_PORT_STATUS_SPEED_1000:
                link->speed = SWITCH_PORT_SPEED_1000;
                break;
        default: