.. | .. |
---|
20 | 20 | #include <linux/of_irq.h> |
---|
21 | 21 | #include <linux/regmap.h> |
---|
22 | 22 | |
---|
23 | | -#include "realtek-smi.h" |
---|
| 23 | +#include "realtek-smi-core.h" |
---|
24 | 24 | |
---|
25 | 25 | #define RTL8366RB_PORT_NUM_CPU 5 |
---|
26 | 26 | #define RTL8366RB_NUM_PORTS 6 |
---|
.. | .. |
---|
35 | 35 | #define RTL8366RB_SGCR_MAX_LENGTH_1522 RTL8366RB_SGCR_MAX_LENGTH(0x0) |
---|
36 | 36 | #define RTL8366RB_SGCR_MAX_LENGTH_1536 RTL8366RB_SGCR_MAX_LENGTH(0x1) |
---|
37 | 37 | #define RTL8366RB_SGCR_MAX_LENGTH_1552 RTL8366RB_SGCR_MAX_LENGTH(0x2) |
---|
38 | | -#define RTL8366RB_SGCR_MAX_LENGTH_9216 RTL8366RB_SGCR_MAX_LENGTH(0x3) |
---|
| 38 | +#define RTL8366RB_SGCR_MAX_LENGTH_16000 RTL8366RB_SGCR_MAX_LENGTH(0x3) |
---|
39 | 39 | #define RTL8366RB_SGCR_EN_VLAN BIT(13) |
---|
40 | 40 | #define RTL8366RB_SGCR_EN_VLAN_4KTB BIT(14) |
---|
41 | 41 | |
---|
.. | .. |
---|
109 | 109 | /* CPU port control reg */ |
---|
110 | 110 | #define RTL8368RB_CPU_CTRL_REG 0x0061 |
---|
111 | 111 | #define RTL8368RB_CPU_PORTS_MSK 0x00FF |
---|
112 | | -/* Enables inserting custom tag length/type 0x8899 */ |
---|
113 | | -#define RTL8368RB_CPU_INSTAG BIT(15) |
---|
| 112 | +/* Disables inserting custom tag length/type 0x8899 */ |
---|
| 113 | +#define RTL8368RB_CPU_NO_TAG BIT(15) |
---|
114 | 114 | |
---|
115 | 115 | #define RTL8366RB_SMAR0 0x0070 /* bits 0..15 */ |
---|
116 | 116 | #define RTL8366RB_SMAR1 0x0071 /* bits 16..31 */ |
---|
.. | .. |
---|
310 | 310 | #define RTL8366RB_GREEN_FEATURE_MSK 0x0007 |
---|
311 | 311 | #define RTL8366RB_GREEN_FEATURE_TX BIT(0) |
---|
312 | 312 | #define RTL8366RB_GREEN_FEATURE_RX BIT(2) |
---|
| 313 | + |
---|
| 314 | +/** |
---|
| 315 | + * struct rtl8366rb - RTL8366RB-specific data |
---|
| 316 | + * @max_mtu: per-port max MTU setting |
---|
| 317 | + */ |
---|
| 318 | +struct rtl8366rb { |
---|
| 319 | + unsigned int max_mtu[RTL8366RB_NUM_PORTS]; |
---|
| 320 | +}; |
---|
313 | 321 | |
---|
314 | 322 | static struct rtl8366_mib_counter rtl8366rb_mib_counters[] = { |
---|
315 | 323 | { 0, 0, 4, "IfInOctets" }, |
---|
.. | .. |
---|
712 | 720 | { |
---|
713 | 721 | struct realtek_smi *smi = ds->priv; |
---|
714 | 722 | const u16 *jam_table; |
---|
| 723 | + struct rtl8366rb *rb; |
---|
715 | 724 | u32 chip_ver = 0; |
---|
716 | 725 | u32 chip_id = 0; |
---|
717 | 726 | int jam_size; |
---|
718 | 727 | u32 val; |
---|
719 | 728 | int ret; |
---|
720 | 729 | int i; |
---|
| 730 | + |
---|
| 731 | + rb = smi->chip_data; |
---|
721 | 732 | |
---|
722 | 733 | ret = regmap_read(smi->map, RTL8366RB_CHIP_ID_REG, &chip_id); |
---|
723 | 734 | if (ret) { |
---|
.. | .. |
---|
844 | 855 | if (ret) |
---|
845 | 856 | return ret; |
---|
846 | 857 | |
---|
847 | | - /* Enable CPU port and enable inserting CPU tag |
---|
| 858 | + /* Enable CPU port with custom DSA tag 8899. |
---|
848 | 859 | * |
---|
849 | | - * Disabling RTL8368RB_CPU_INSTAG here will change the behaviour |
---|
850 | | - * of the switch totally and it will start talking Realtek RRCP |
---|
851 | | - * internally. It is probably possible to experiment with this, |
---|
852 | | - * but then the kernel needs to understand and handle RRCP first. |
---|
| 860 | + * If you set RTL8368RB_CPU_NO_TAG (bit 15) in this registers |
---|
| 861 | + * the custom tag is turned off. |
---|
853 | 862 | */ |
---|
854 | 863 | ret = regmap_update_bits(smi->map, RTL8368RB_CPU_CTRL_REG, |
---|
855 | 864 | 0xFFFF, |
---|
856 | | - RTL8368RB_CPU_INSTAG | BIT(smi->cpu_port)); |
---|
| 865 | + BIT(smi->cpu_port)); |
---|
857 | 866 | if (ret) |
---|
858 | 867 | return ret; |
---|
859 | 868 | |
---|
.. | .. |
---|
870 | 879 | RTL8366RB_SGCR_MAX_LENGTH_1536); |
---|
871 | 880 | if (ret) |
---|
872 | 881 | return ret; |
---|
| 882 | + for (i = 0; i < RTL8366RB_NUM_PORTS; i++) |
---|
| 883 | + /* layer 2 size, see rtl8366rb_change_mtu() */ |
---|
| 884 | + rb->max_mtu[i] = 1532; |
---|
873 | 885 | |
---|
874 | 886 | /* Enable learning for all ports */ |
---|
875 | 887 | ret = regmap_write(smi->map, RTL8366RB_SSCR0, 0); |
---|
.. | .. |
---|
964 | 976 | } |
---|
965 | 977 | |
---|
966 | 978 | static enum dsa_tag_protocol rtl8366_get_tag_protocol(struct dsa_switch *ds, |
---|
967 | | - int port) |
---|
| 979 | + int port, |
---|
| 980 | + enum dsa_tag_protocol mp) |
---|
968 | 981 | { |
---|
969 | | - /* For now, the RTL switches are handled without any custom tags. |
---|
970 | | - * |
---|
971 | | - * It is possible to turn on "custom tags" by removing the |
---|
972 | | - * RTL8368RB_CPU_INSTAG flag when enabling the port but what it |
---|
973 | | - * does is unfamiliar to DSA: ethernet frames of type 8899, the Realtek |
---|
974 | | - * Remote Control Protocol (RRCP) start to appear on the CPU port of |
---|
975 | | - * the device. So this is not the ordinary few extra bytes in the |
---|
976 | | - * frame. Instead it appears that the switch starts to talk Realtek |
---|
977 | | - * RRCP internally which means a pretty complex RRCP implementation |
---|
978 | | - * decoding and responding the RRCP protocol is needed to exploit this. |
---|
979 | | - * |
---|
980 | | - * The OpenRRCP project (dormant since 2009) have reverse-egineered |
---|
981 | | - * parts of the protocol. |
---|
982 | | - */ |
---|
983 | | - return DSA_TAG_PROTO_NONE; |
---|
| 982 | + /* This switch uses the 4 byte protocol A Realtek DSA tag */ |
---|
| 983 | + return DSA_TAG_PROTO_RTL4_A; |
---|
984 | 984 | } |
---|
985 | 985 | |
---|
986 | | -static void rtl8366rb_adjust_link(struct dsa_switch *ds, int port, |
---|
987 | | - struct phy_device *phydev) |
---|
| 986 | +static void |
---|
| 987 | +rtl8366rb_mac_link_up(struct dsa_switch *ds, int port, unsigned int mode, |
---|
| 988 | + phy_interface_t interface, struct phy_device *phydev, |
---|
| 989 | + int speed, int duplex, bool tx_pause, bool rx_pause) |
---|
988 | 990 | { |
---|
989 | 991 | struct realtek_smi *smi = ds->priv; |
---|
990 | 992 | int ret; |
---|
.. | .. |
---|
992 | 994 | if (port != smi->cpu_port) |
---|
993 | 995 | return; |
---|
994 | 996 | |
---|
995 | | - dev_info(smi->dev, "adjust link on CPU port (%d)\n", port); |
---|
| 997 | + dev_dbg(smi->dev, "MAC link up on CPU port (%d)\n", port); |
---|
996 | 998 | |
---|
997 | 999 | /* Force the fixed CPU port into 1Gbit mode, no autonegotiation */ |
---|
998 | 1000 | ret = regmap_update_bits(smi->map, RTL8366RB_MAC_FORCE_CTRL_REG, |
---|
999 | 1001 | BIT(port), BIT(port)); |
---|
1000 | | - if (ret) |
---|
| 1002 | + if (ret) { |
---|
| 1003 | + dev_err(smi->dev, "failed to force 1Gbit on CPU port\n"); |
---|
1001 | 1004 | return; |
---|
| 1005 | + } |
---|
1002 | 1006 | |
---|
1003 | 1007 | ret = regmap_update_bits(smi->map, RTL8366RB_PAACR2, |
---|
1004 | 1008 | 0xFF00U, |
---|
1005 | 1009 | RTL8366RB_PAACR_CPU_PORT << 8); |
---|
1006 | | - if (ret) |
---|
| 1010 | + if (ret) { |
---|
| 1011 | + dev_err(smi->dev, "failed to set PAACR on CPU port\n"); |
---|
1007 | 1012 | return; |
---|
| 1013 | + } |
---|
1008 | 1014 | |
---|
1009 | 1015 | /* Enable the CPU port */ |
---|
1010 | 1016 | ret = regmap_update_bits(smi->map, RTL8366RB_PECR, BIT(port), |
---|
1011 | 1017 | 0); |
---|
1012 | | - if (ret) |
---|
| 1018 | + if (ret) { |
---|
| 1019 | + dev_err(smi->dev, "failed to enable the CPU port\n"); |
---|
1013 | 1020 | return; |
---|
| 1021 | + } |
---|
| 1022 | +} |
---|
| 1023 | + |
---|
| 1024 | +static void |
---|
| 1025 | +rtl8366rb_mac_link_down(struct dsa_switch *ds, int port, unsigned int mode, |
---|
| 1026 | + phy_interface_t interface) |
---|
| 1027 | +{ |
---|
| 1028 | + struct realtek_smi *smi = ds->priv; |
---|
| 1029 | + int ret; |
---|
| 1030 | + |
---|
| 1031 | + if (port != smi->cpu_port) |
---|
| 1032 | + return; |
---|
| 1033 | + |
---|
| 1034 | + dev_dbg(smi->dev, "MAC link down on CPU port (%d)\n", port); |
---|
| 1035 | + |
---|
| 1036 | + /* Disable the CPU port */ |
---|
| 1037 | + ret = regmap_update_bits(smi->map, RTL8366RB_PECR, BIT(port), |
---|
| 1038 | + BIT(port)); |
---|
| 1039 | + if (ret) { |
---|
| 1040 | + dev_err(smi->dev, "failed to disable the CPU port\n"); |
---|
| 1041 | + return; |
---|
| 1042 | + } |
---|
1014 | 1043 | } |
---|
1015 | 1044 | |
---|
1016 | 1045 | static void rb8366rb_set_port_led(struct realtek_smi *smi, |
---|
.. | .. |
---|
1077 | 1106 | } |
---|
1078 | 1107 | |
---|
1079 | 1108 | static void |
---|
1080 | | -rtl8366rb_port_disable(struct dsa_switch *ds, int port, |
---|
1081 | | - struct phy_device *phy) |
---|
| 1109 | +rtl8366rb_port_disable(struct dsa_switch *ds, int port) |
---|
1082 | 1110 | { |
---|
1083 | 1111 | struct realtek_smi *smi = ds->priv; |
---|
1084 | 1112 | int ret; |
---|
.. | .. |
---|
1090 | 1118 | return; |
---|
1091 | 1119 | |
---|
1092 | 1120 | rb8366rb_set_port_led(smi, port, false); |
---|
| 1121 | +} |
---|
| 1122 | + |
---|
| 1123 | +static int rtl8366rb_change_mtu(struct dsa_switch *ds, int port, int new_mtu) |
---|
| 1124 | +{ |
---|
| 1125 | + struct realtek_smi *smi = ds->priv; |
---|
| 1126 | + struct rtl8366rb *rb; |
---|
| 1127 | + unsigned int max_mtu; |
---|
| 1128 | + u32 len; |
---|
| 1129 | + int i; |
---|
| 1130 | + |
---|
| 1131 | + /* Cache the per-port MTU setting */ |
---|
| 1132 | + rb = smi->chip_data; |
---|
| 1133 | + rb->max_mtu[port] = new_mtu; |
---|
| 1134 | + |
---|
| 1135 | + /* Roof out the MTU for the entire switch to the greatest |
---|
| 1136 | + * common denominator: the biggest set for any one port will |
---|
| 1137 | + * be the biggest MTU for the switch. |
---|
| 1138 | + * |
---|
| 1139 | + * The first setting, 1522 bytes, is max IP packet 1500 bytes, |
---|
| 1140 | + * plus ethernet header, 1518 bytes, plus CPU tag, 4 bytes. |
---|
| 1141 | + * This function should consider the parameter an SDU, so the |
---|
| 1142 | + * MTU passed for this setting is 1518 bytes. The same logic |
---|
| 1143 | + * of subtracting the DSA tag of 4 bytes apply to the other |
---|
| 1144 | + * settings. |
---|
| 1145 | + */ |
---|
| 1146 | + max_mtu = 1518; |
---|
| 1147 | + for (i = 0; i < RTL8366RB_NUM_PORTS; i++) { |
---|
| 1148 | + if (rb->max_mtu[i] > max_mtu) |
---|
| 1149 | + max_mtu = rb->max_mtu[i]; |
---|
| 1150 | + } |
---|
| 1151 | + if (max_mtu <= 1518) |
---|
| 1152 | + len = RTL8366RB_SGCR_MAX_LENGTH_1522; |
---|
| 1153 | + else if (max_mtu > 1518 && max_mtu <= 1532) |
---|
| 1154 | + len = RTL8366RB_SGCR_MAX_LENGTH_1536; |
---|
| 1155 | + else if (max_mtu > 1532 && max_mtu <= 1548) |
---|
| 1156 | + len = RTL8366RB_SGCR_MAX_LENGTH_1552; |
---|
| 1157 | + else |
---|
| 1158 | + len = RTL8366RB_SGCR_MAX_LENGTH_16000; |
---|
| 1159 | + |
---|
| 1160 | + return regmap_update_bits(smi->map, RTL8366RB_SGCR, |
---|
| 1161 | + RTL8366RB_SGCR_MAX_LENGTH_MASK, |
---|
| 1162 | + len); |
---|
| 1163 | +} |
---|
| 1164 | + |
---|
| 1165 | +static int rtl8366rb_max_mtu(struct dsa_switch *ds, int port) |
---|
| 1166 | +{ |
---|
| 1167 | + /* The max MTU is 16000 bytes, so we subtract the CPU tag |
---|
| 1168 | + * and the max presented to the system is 15996 bytes. |
---|
| 1169 | + */ |
---|
| 1170 | + return 15996; |
---|
1093 | 1171 | } |
---|
1094 | 1172 | |
---|
1095 | 1173 | static int rtl8366rb_get_vlan_4k(struct realtek_smi *smi, u32 vid, |
---|
.. | .. |
---|
1420 | 1498 | static const struct dsa_switch_ops rtl8366rb_switch_ops = { |
---|
1421 | 1499 | .get_tag_protocol = rtl8366_get_tag_protocol, |
---|
1422 | 1500 | .setup = rtl8366rb_setup, |
---|
1423 | | - .adjust_link = rtl8366rb_adjust_link, |
---|
| 1501 | + .phylink_mac_link_up = rtl8366rb_mac_link_up, |
---|
| 1502 | + .phylink_mac_link_down = rtl8366rb_mac_link_down, |
---|
1424 | 1503 | .get_strings = rtl8366_get_strings, |
---|
1425 | 1504 | .get_ethtool_stats = rtl8366_get_ethtool_stats, |
---|
1426 | 1505 | .get_sset_count = rtl8366_get_sset_count, |
---|
.. | .. |
---|
1430 | 1509 | .port_vlan_del = rtl8366_vlan_del, |
---|
1431 | 1510 | .port_enable = rtl8366rb_port_enable, |
---|
1432 | 1511 | .port_disable = rtl8366rb_port_disable, |
---|
| 1512 | + .port_change_mtu = rtl8366rb_change_mtu, |
---|
| 1513 | + .port_max_mtu = rtl8366rb_max_mtu, |
---|
1433 | 1514 | }; |
---|
1434 | 1515 | |
---|
1435 | 1516 | static const struct realtek_smi_ops rtl8366rb_smi_ops = { |
---|
.. | .. |
---|
1454 | 1535 | .clk_delay = 10, |
---|
1455 | 1536 | .cmd_read = 0xa9, |
---|
1456 | 1537 | .cmd_write = 0xa8, |
---|
| 1538 | + .chip_data_sz = sizeof(struct rtl8366rb), |
---|
1457 | 1539 | }; |
---|
1458 | 1540 | EXPORT_SYMBOL_GPL(rtl8366rb_variant); |
---|