0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/net_tstamp.h>
0009 #include <linux/phylink.h>
0010 #include <linux/platform_device.h>
0011 #include <linux/pm_runtime.h>
0012
0013 #include "am65-cpsw-nuss.h"
0014 #include "cpsw_ale.h"
0015 #include "am65-cpts.h"
0016
0017 #define AM65_CPSW_REGDUMP_VER 0x1
0018
0019 enum {
0020 AM65_CPSW_REGDUMP_MOD_NUSS = 1,
0021 AM65_CPSW_REGDUMP_MOD_RGMII_STATUS = 2,
0022 AM65_CPSW_REGDUMP_MOD_MDIO = 3,
0023 AM65_CPSW_REGDUMP_MOD_CPSW = 4,
0024 AM65_CPSW_REGDUMP_MOD_CPSW_P0 = 5,
0025 AM65_CPSW_REGDUMP_MOD_CPSW_P1 = 6,
0026 AM65_CPSW_REGDUMP_MOD_CPSW_CPTS = 7,
0027 AM65_CPSW_REGDUMP_MOD_CPSW_ALE = 8,
0028 AM65_CPSW_REGDUMP_MOD_CPSW_ALE_TBL = 9,
0029 AM65_CPSW_REGDUMP_MOD_LAST,
0030 };
0031
0032
0033
0034
0035
0036
0037
0038
0039 struct am65_cpsw_regdump_hdr {
0040 u32 module_id;
0041 u32 len;
0042 };
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056 struct am65_cpsw_regdump_item {
0057 struct am65_cpsw_regdump_hdr hdr;
0058 u32 start_ofs;
0059 u32 end_ofs;
0060 };
0061
0062 #define AM65_CPSW_REGDUMP_REC(mod, start, end) { \
0063 .hdr.module_id = (mod), \
0064 .hdr.len = (end + 4 - start) * 2 + \
0065 sizeof(struct am65_cpsw_regdump_hdr), \
0066 .start_ofs = (start), \
0067 .end_ofs = end, \
0068 }
0069
0070 static const struct am65_cpsw_regdump_item am65_cpsw_regdump[] = {
0071 AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_NUSS, 0x0, 0x1c),
0072 AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_RGMII_STATUS, 0x30, 0x4c),
0073 AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_MDIO, 0xf00, 0xffc),
0074 AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW, 0x20000, 0x2011c),
0075 AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW_P0, 0x21000, 0x21320),
0076 AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW_P1, 0x22000, 0x223a4),
0077 AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW_CPTS,
0078 0x3d000, 0x3d048),
0079 AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW_ALE, 0x3e000, 0x3e13c),
0080 AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW_ALE_TBL, 0, 0),
0081 };
0082
0083 struct am65_cpsw_stats_regs {
0084 u32 rx_good_frames;
0085 u32 rx_broadcast_frames;
0086 u32 rx_multicast_frames;
0087 u32 rx_pause_frames;
0088 u32 rx_crc_errors;
0089 u32 rx_align_code_errors;
0090 u32 rx_oversized_frames;
0091 u32 rx_jabber_frames;
0092 u32 rx_undersized_frames;
0093 u32 rx_fragments;
0094 u32 ale_drop;
0095 u32 ale_overrun_drop;
0096 u32 rx_octets;
0097 u32 tx_good_frames;
0098 u32 tx_broadcast_frames;
0099 u32 tx_multicast_frames;
0100 u32 tx_pause_frames;
0101 u32 tx_deferred_frames;
0102 u32 tx_collision_frames;
0103 u32 tx_single_coll_frames;
0104 u32 tx_mult_coll_frames;
0105 u32 tx_excessive_collisions;
0106 u32 tx_late_collisions;
0107 u32 rx_ipg_error;
0108 u32 tx_carrier_sense_errors;
0109 u32 tx_octets;
0110 u32 tx_64B_frames;
0111 u32 tx_65_to_127B_frames;
0112 u32 tx_128_to_255B_frames;
0113 u32 tx_256_to_511B_frames;
0114 u32 tx_512_to_1023B_frames;
0115 u32 tx_1024B_frames;
0116 u32 net_octets;
0117 u32 rx_bottom_fifo_drop;
0118 u32 rx_port_mask_drop;
0119 u32 rx_top_fifo_drop;
0120 u32 ale_rate_limit_drop;
0121 u32 ale_vid_ingress_drop;
0122 u32 ale_da_eq_sa_drop;
0123 u32 ale_block_drop;
0124 u32 ale_secure_drop;
0125 u32 ale_auth_drop;
0126 u32 ale_unknown_ucast;
0127 u32 ale_unknown_ucast_bytes;
0128 u32 ale_unknown_mcast;
0129 u32 ale_unknown_mcast_bytes;
0130 u32 ale_unknown_bcast;
0131 u32 ale_unknown_bcast_bytes;
0132 u32 ale_pol_match;
0133 u32 ale_pol_match_red;
0134 u32 ale_pol_match_yellow;
0135 u32 ale_mcast_sa_drop;
0136 u32 ale_dual_vlan_drop;
0137 u32 ale_len_err_drop;
0138 u32 ale_ip_next_hdr_drop;
0139 u32 ale_ipv4_frag_drop;
0140 u32 __rsvd_1[24];
0141 u32 iet_rx_assembly_err;
0142 u32 iet_rx_assembly_ok;
0143 u32 iet_rx_smd_err;
0144 u32 iet_rx_frag;
0145 u32 iet_tx_hold;
0146 u32 iet_tx_frag;
0147 u32 __rsvd_2[9];
0148 u32 tx_mem_protect_err;
0149
0150 u32 tx_pri0;
0151 u32 tx_pri1;
0152 u32 tx_pri2;
0153 u32 tx_pri3;
0154 u32 tx_pri4;
0155 u32 tx_pri5;
0156 u32 tx_pri6;
0157 u32 tx_pri7;
0158 u32 tx_pri0_bcnt;
0159 u32 tx_pri1_bcnt;
0160 u32 tx_pri2_bcnt;
0161 u32 tx_pri3_bcnt;
0162 u32 tx_pri4_bcnt;
0163 u32 tx_pri5_bcnt;
0164 u32 tx_pri6_bcnt;
0165 u32 tx_pri7_bcnt;
0166 u32 tx_pri0_drop;
0167 u32 tx_pri1_drop;
0168 u32 tx_pri2_drop;
0169 u32 tx_pri3_drop;
0170 u32 tx_pri4_drop;
0171 u32 tx_pri5_drop;
0172 u32 tx_pri6_drop;
0173 u32 tx_pri7_drop;
0174 u32 tx_pri0_drop_bcnt;
0175 u32 tx_pri1_drop_bcnt;
0176 u32 tx_pri2_drop_bcnt;
0177 u32 tx_pri3_drop_bcnt;
0178 u32 tx_pri4_drop_bcnt;
0179 u32 tx_pri5_drop_bcnt;
0180 u32 tx_pri6_drop_bcnt;
0181 u32 tx_pri7_drop_bcnt;
0182 };
0183
0184 struct am65_cpsw_ethtool_stat {
0185 char desc[ETH_GSTRING_LEN];
0186 int offset;
0187 };
0188
0189 #define AM65_CPSW_STATS(prefix, field) \
0190 { \
0191 #prefix#field, \
0192 offsetof(struct am65_cpsw_stats_regs, field) \
0193 }
0194
0195 static const struct am65_cpsw_ethtool_stat am65_host_stats[] = {
0196 AM65_CPSW_STATS(p0_, rx_good_frames),
0197 AM65_CPSW_STATS(p0_, rx_broadcast_frames),
0198 AM65_CPSW_STATS(p0_, rx_multicast_frames),
0199 AM65_CPSW_STATS(p0_, rx_crc_errors),
0200 AM65_CPSW_STATS(p0_, rx_oversized_frames),
0201 AM65_CPSW_STATS(p0_, rx_undersized_frames),
0202 AM65_CPSW_STATS(p0_, ale_drop),
0203 AM65_CPSW_STATS(p0_, ale_overrun_drop),
0204 AM65_CPSW_STATS(p0_, rx_octets),
0205 AM65_CPSW_STATS(p0_, tx_good_frames),
0206 AM65_CPSW_STATS(p0_, tx_broadcast_frames),
0207 AM65_CPSW_STATS(p0_, tx_multicast_frames),
0208 AM65_CPSW_STATS(p0_, tx_octets),
0209 AM65_CPSW_STATS(p0_, tx_64B_frames),
0210 AM65_CPSW_STATS(p0_, tx_65_to_127B_frames),
0211 AM65_CPSW_STATS(p0_, tx_128_to_255B_frames),
0212 AM65_CPSW_STATS(p0_, tx_256_to_511B_frames),
0213 AM65_CPSW_STATS(p0_, tx_512_to_1023B_frames),
0214 AM65_CPSW_STATS(p0_, tx_1024B_frames),
0215 AM65_CPSW_STATS(p0_, net_octets),
0216 AM65_CPSW_STATS(p0_, rx_bottom_fifo_drop),
0217 AM65_CPSW_STATS(p0_, rx_port_mask_drop),
0218 AM65_CPSW_STATS(p0_, rx_top_fifo_drop),
0219 AM65_CPSW_STATS(p0_, ale_rate_limit_drop),
0220 AM65_CPSW_STATS(p0_, ale_vid_ingress_drop),
0221 AM65_CPSW_STATS(p0_, ale_da_eq_sa_drop),
0222 AM65_CPSW_STATS(p0_, ale_block_drop),
0223 AM65_CPSW_STATS(p0_, ale_secure_drop),
0224 AM65_CPSW_STATS(p0_, ale_auth_drop),
0225 AM65_CPSW_STATS(p0_, ale_unknown_ucast),
0226 AM65_CPSW_STATS(p0_, ale_unknown_ucast_bytes),
0227 AM65_CPSW_STATS(p0_, ale_unknown_mcast),
0228 AM65_CPSW_STATS(p0_, ale_unknown_mcast_bytes),
0229 AM65_CPSW_STATS(p0_, ale_unknown_bcast),
0230 AM65_CPSW_STATS(p0_, ale_unknown_bcast_bytes),
0231 AM65_CPSW_STATS(p0_, ale_pol_match),
0232 AM65_CPSW_STATS(p0_, ale_pol_match_red),
0233 AM65_CPSW_STATS(p0_, ale_pol_match_yellow),
0234 AM65_CPSW_STATS(p0_, ale_mcast_sa_drop),
0235 AM65_CPSW_STATS(p0_, ale_dual_vlan_drop),
0236 AM65_CPSW_STATS(p0_, ale_len_err_drop),
0237 AM65_CPSW_STATS(p0_, ale_ip_next_hdr_drop),
0238 AM65_CPSW_STATS(p0_, ale_ipv4_frag_drop),
0239 AM65_CPSW_STATS(p0_, tx_mem_protect_err),
0240 AM65_CPSW_STATS(p0_, tx_pri0),
0241 AM65_CPSW_STATS(p0_, tx_pri1),
0242 AM65_CPSW_STATS(p0_, tx_pri2),
0243 AM65_CPSW_STATS(p0_, tx_pri3),
0244 AM65_CPSW_STATS(p0_, tx_pri4),
0245 AM65_CPSW_STATS(p0_, tx_pri5),
0246 AM65_CPSW_STATS(p0_, tx_pri6),
0247 AM65_CPSW_STATS(p0_, tx_pri7),
0248 AM65_CPSW_STATS(p0_, tx_pri0_bcnt),
0249 AM65_CPSW_STATS(p0_, tx_pri1_bcnt),
0250 AM65_CPSW_STATS(p0_, tx_pri2_bcnt),
0251 AM65_CPSW_STATS(p0_, tx_pri3_bcnt),
0252 AM65_CPSW_STATS(p0_, tx_pri4_bcnt),
0253 AM65_CPSW_STATS(p0_, tx_pri5_bcnt),
0254 AM65_CPSW_STATS(p0_, tx_pri6_bcnt),
0255 AM65_CPSW_STATS(p0_, tx_pri7_bcnt),
0256 AM65_CPSW_STATS(p0_, tx_pri0_drop),
0257 AM65_CPSW_STATS(p0_, tx_pri1_drop),
0258 AM65_CPSW_STATS(p0_, tx_pri2_drop),
0259 AM65_CPSW_STATS(p0_, tx_pri3_drop),
0260 AM65_CPSW_STATS(p0_, tx_pri4_drop),
0261 AM65_CPSW_STATS(p0_, tx_pri5_drop),
0262 AM65_CPSW_STATS(p0_, tx_pri6_drop),
0263 AM65_CPSW_STATS(p0_, tx_pri7_drop),
0264 AM65_CPSW_STATS(p0_, tx_pri0_drop_bcnt),
0265 AM65_CPSW_STATS(p0_, tx_pri1_drop_bcnt),
0266 AM65_CPSW_STATS(p0_, tx_pri2_drop_bcnt),
0267 AM65_CPSW_STATS(p0_, tx_pri3_drop_bcnt),
0268 AM65_CPSW_STATS(p0_, tx_pri4_drop_bcnt),
0269 AM65_CPSW_STATS(p0_, tx_pri5_drop_bcnt),
0270 AM65_CPSW_STATS(p0_, tx_pri6_drop_bcnt),
0271 AM65_CPSW_STATS(p0_, tx_pri7_drop_bcnt),
0272 };
0273
0274 static const struct am65_cpsw_ethtool_stat am65_slave_stats[] = {
0275 AM65_CPSW_STATS(, rx_good_frames),
0276 AM65_CPSW_STATS(, rx_broadcast_frames),
0277 AM65_CPSW_STATS(, rx_multicast_frames),
0278 AM65_CPSW_STATS(, rx_pause_frames),
0279 AM65_CPSW_STATS(, rx_crc_errors),
0280 AM65_CPSW_STATS(, rx_align_code_errors),
0281 AM65_CPSW_STATS(, rx_oversized_frames),
0282 AM65_CPSW_STATS(, rx_jabber_frames),
0283 AM65_CPSW_STATS(, rx_undersized_frames),
0284 AM65_CPSW_STATS(, rx_fragments),
0285 AM65_CPSW_STATS(, ale_drop),
0286 AM65_CPSW_STATS(, ale_overrun_drop),
0287 AM65_CPSW_STATS(, rx_octets),
0288 AM65_CPSW_STATS(, tx_good_frames),
0289 AM65_CPSW_STATS(, tx_broadcast_frames),
0290 AM65_CPSW_STATS(, tx_multicast_frames),
0291 AM65_CPSW_STATS(, tx_pause_frames),
0292 AM65_CPSW_STATS(, tx_deferred_frames),
0293 AM65_CPSW_STATS(, tx_collision_frames),
0294 AM65_CPSW_STATS(, tx_single_coll_frames),
0295 AM65_CPSW_STATS(, tx_mult_coll_frames),
0296 AM65_CPSW_STATS(, tx_excessive_collisions),
0297 AM65_CPSW_STATS(, tx_late_collisions),
0298 AM65_CPSW_STATS(, rx_ipg_error),
0299 AM65_CPSW_STATS(, tx_carrier_sense_errors),
0300 AM65_CPSW_STATS(, tx_octets),
0301 AM65_CPSW_STATS(, tx_64B_frames),
0302 AM65_CPSW_STATS(, tx_65_to_127B_frames),
0303 AM65_CPSW_STATS(, tx_128_to_255B_frames),
0304 AM65_CPSW_STATS(, tx_256_to_511B_frames),
0305 AM65_CPSW_STATS(, tx_512_to_1023B_frames),
0306 AM65_CPSW_STATS(, tx_1024B_frames),
0307 AM65_CPSW_STATS(, net_octets),
0308 AM65_CPSW_STATS(, rx_bottom_fifo_drop),
0309 AM65_CPSW_STATS(, rx_port_mask_drop),
0310 AM65_CPSW_STATS(, rx_top_fifo_drop),
0311 AM65_CPSW_STATS(, ale_rate_limit_drop),
0312 AM65_CPSW_STATS(, ale_vid_ingress_drop),
0313 AM65_CPSW_STATS(, ale_da_eq_sa_drop),
0314 AM65_CPSW_STATS(, ale_block_drop),
0315 AM65_CPSW_STATS(, ale_secure_drop),
0316 AM65_CPSW_STATS(, ale_auth_drop),
0317 AM65_CPSW_STATS(, ale_unknown_ucast),
0318 AM65_CPSW_STATS(, ale_unknown_ucast_bytes),
0319 AM65_CPSW_STATS(, ale_unknown_mcast),
0320 AM65_CPSW_STATS(, ale_unknown_mcast_bytes),
0321 AM65_CPSW_STATS(, ale_unknown_bcast),
0322 AM65_CPSW_STATS(, ale_unknown_bcast_bytes),
0323 AM65_CPSW_STATS(, ale_pol_match),
0324 AM65_CPSW_STATS(, ale_pol_match_red),
0325 AM65_CPSW_STATS(, ale_pol_match_yellow),
0326 AM65_CPSW_STATS(, ale_mcast_sa_drop),
0327 AM65_CPSW_STATS(, ale_dual_vlan_drop),
0328 AM65_CPSW_STATS(, ale_len_err_drop),
0329 AM65_CPSW_STATS(, ale_ip_next_hdr_drop),
0330 AM65_CPSW_STATS(, ale_ipv4_frag_drop),
0331 AM65_CPSW_STATS(, iet_rx_assembly_err),
0332 AM65_CPSW_STATS(, iet_rx_assembly_ok),
0333 AM65_CPSW_STATS(, iet_rx_smd_err),
0334 AM65_CPSW_STATS(, iet_rx_frag),
0335 AM65_CPSW_STATS(, iet_tx_hold),
0336 AM65_CPSW_STATS(, iet_tx_frag),
0337 AM65_CPSW_STATS(, tx_mem_protect_err),
0338 AM65_CPSW_STATS(, tx_pri0),
0339 AM65_CPSW_STATS(, tx_pri1),
0340 AM65_CPSW_STATS(, tx_pri2),
0341 AM65_CPSW_STATS(, tx_pri3),
0342 AM65_CPSW_STATS(, tx_pri4),
0343 AM65_CPSW_STATS(, tx_pri5),
0344 AM65_CPSW_STATS(, tx_pri6),
0345 AM65_CPSW_STATS(, tx_pri7),
0346 AM65_CPSW_STATS(, tx_pri0_bcnt),
0347 AM65_CPSW_STATS(, tx_pri1_bcnt),
0348 AM65_CPSW_STATS(, tx_pri2_bcnt),
0349 AM65_CPSW_STATS(, tx_pri3_bcnt),
0350 AM65_CPSW_STATS(, tx_pri4_bcnt),
0351 AM65_CPSW_STATS(, tx_pri5_bcnt),
0352 AM65_CPSW_STATS(, tx_pri6_bcnt),
0353 AM65_CPSW_STATS(, tx_pri7_bcnt),
0354 AM65_CPSW_STATS(, tx_pri0_drop),
0355 AM65_CPSW_STATS(, tx_pri1_drop),
0356 AM65_CPSW_STATS(, tx_pri2_drop),
0357 AM65_CPSW_STATS(, tx_pri3_drop),
0358 AM65_CPSW_STATS(, tx_pri4_drop),
0359 AM65_CPSW_STATS(, tx_pri5_drop),
0360 AM65_CPSW_STATS(, tx_pri6_drop),
0361 AM65_CPSW_STATS(, tx_pri7_drop),
0362 AM65_CPSW_STATS(, tx_pri0_drop_bcnt),
0363 AM65_CPSW_STATS(, tx_pri1_drop_bcnt),
0364 AM65_CPSW_STATS(, tx_pri2_drop_bcnt),
0365 AM65_CPSW_STATS(, tx_pri3_drop_bcnt),
0366 AM65_CPSW_STATS(, tx_pri4_drop_bcnt),
0367 AM65_CPSW_STATS(, tx_pri5_drop_bcnt),
0368 AM65_CPSW_STATS(, tx_pri6_drop_bcnt),
0369 AM65_CPSW_STATS(, tx_pri7_drop_bcnt),
0370 };
0371
0372
0373 static const char am65_cpsw_ethtool_priv_flags[][ETH_GSTRING_LEN] = {
0374 #define AM65_CPSW_PRIV_P0_RX_PTYPE_RROBIN BIT(0)
0375 "p0-rx-ptype-rrobin",
0376 };
0377
0378 static int am65_cpsw_ethtool_op_begin(struct net_device *ndev)
0379 {
0380 struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
0381 int ret;
0382
0383 ret = pm_runtime_resume_and_get(common->dev);
0384 if (ret < 0)
0385 dev_err(common->dev, "ethtool begin failed %d\n", ret);
0386
0387 return ret;
0388 }
0389
0390 static void am65_cpsw_ethtool_op_complete(struct net_device *ndev)
0391 {
0392 struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
0393 int ret;
0394
0395 ret = pm_runtime_put(common->dev);
0396 if (ret < 0 && ret != -EBUSY)
0397 dev_err(common->dev, "ethtool complete failed %d\n", ret);
0398 }
0399
0400 static void am65_cpsw_get_drvinfo(struct net_device *ndev,
0401 struct ethtool_drvinfo *info)
0402 {
0403 struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
0404
0405 strlcpy(info->driver, dev_driver_string(common->dev),
0406 sizeof(info->driver));
0407 strlcpy(info->bus_info, dev_name(common->dev), sizeof(info->bus_info));
0408 }
0409
0410 static u32 am65_cpsw_get_msglevel(struct net_device *ndev)
0411 {
0412 struct am65_cpsw_ndev_priv *priv = am65_ndev_to_priv(ndev);
0413
0414 return priv->msg_enable;
0415 }
0416
0417 static void am65_cpsw_set_msglevel(struct net_device *ndev, u32 value)
0418 {
0419 struct am65_cpsw_ndev_priv *priv = am65_ndev_to_priv(ndev);
0420
0421 priv->msg_enable = value;
0422 }
0423
0424 static void am65_cpsw_get_channels(struct net_device *ndev,
0425 struct ethtool_channels *ch)
0426 {
0427 struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
0428
0429 ch->max_rx = AM65_CPSW_MAX_RX_QUEUES;
0430 ch->max_tx = AM65_CPSW_MAX_TX_QUEUES;
0431 ch->rx_count = AM65_CPSW_MAX_RX_QUEUES;
0432 ch->tx_count = common->tx_ch_num;
0433 }
0434
0435 static int am65_cpsw_set_channels(struct net_device *ndev,
0436 struct ethtool_channels *chs)
0437 {
0438 struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
0439
0440 if (!chs->rx_count || !chs->tx_count)
0441 return -EINVAL;
0442
0443
0444
0445
0446 if (common->usage_count)
0447 return -EBUSY;
0448
0449 am65_cpsw_nuss_remove_tx_chns(common);
0450
0451 return am65_cpsw_nuss_update_tx_chns(common, chs->tx_count);
0452 }
0453
0454 static void
0455 am65_cpsw_get_ringparam(struct net_device *ndev,
0456 struct ethtool_ringparam *ering,
0457 struct kernel_ethtool_ringparam *kernel_ering,
0458 struct netlink_ext_ack *extack)
0459 {
0460 struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
0461
0462
0463 ering->tx_pending = common->tx_chns[0].descs_num;
0464 ering->rx_pending = common->rx_chns.descs_num;
0465 }
0466
0467 static void am65_cpsw_get_pauseparam(struct net_device *ndev,
0468 struct ethtool_pauseparam *pause)
0469 {
0470 struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
0471
0472 phylink_ethtool_get_pauseparam(salve->phylink, pause);
0473 }
0474
0475 static int am65_cpsw_set_pauseparam(struct net_device *ndev,
0476 struct ethtool_pauseparam *pause)
0477 {
0478 struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
0479
0480 return phylink_ethtool_set_pauseparam(salve->phylink, pause);
0481 }
0482
0483 static void am65_cpsw_get_wol(struct net_device *ndev,
0484 struct ethtool_wolinfo *wol)
0485 {
0486 struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
0487
0488 phylink_ethtool_get_wol(salve->phylink, wol);
0489 }
0490
0491 static int am65_cpsw_set_wol(struct net_device *ndev,
0492 struct ethtool_wolinfo *wol)
0493 {
0494 struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
0495
0496 return phylink_ethtool_set_wol(salve->phylink, wol);
0497 }
0498
0499 static int am65_cpsw_get_link_ksettings(struct net_device *ndev,
0500 struct ethtool_link_ksettings *ecmd)
0501 {
0502 struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
0503
0504 return phylink_ethtool_ksettings_get(salve->phylink, ecmd);
0505 }
0506
0507 static int
0508 am65_cpsw_set_link_ksettings(struct net_device *ndev,
0509 const struct ethtool_link_ksettings *ecmd)
0510 {
0511 struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
0512
0513 return phylink_ethtool_ksettings_set(salve->phylink, ecmd);
0514 }
0515
0516 static int am65_cpsw_get_eee(struct net_device *ndev, struct ethtool_eee *edata)
0517 {
0518 struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
0519
0520 return phylink_ethtool_get_eee(salve->phylink, edata);
0521 }
0522
0523 static int am65_cpsw_set_eee(struct net_device *ndev, struct ethtool_eee *edata)
0524 {
0525 struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
0526
0527 return phylink_ethtool_set_eee(salve->phylink, edata);
0528 }
0529
0530 static int am65_cpsw_nway_reset(struct net_device *ndev)
0531 {
0532 struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
0533
0534 return phylink_ethtool_nway_reset(salve->phylink);
0535 }
0536
0537 static int am65_cpsw_get_regs_len(struct net_device *ndev)
0538 {
0539 struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
0540 u32 ale_entries, i, regdump_len = 0;
0541
0542 ale_entries = cpsw_ale_get_num_entries(common->ale);
0543 for (i = 0; i < ARRAY_SIZE(am65_cpsw_regdump); i++) {
0544 if (am65_cpsw_regdump[i].hdr.module_id ==
0545 AM65_CPSW_REGDUMP_MOD_CPSW_ALE_TBL) {
0546 regdump_len += sizeof(struct am65_cpsw_regdump_hdr);
0547 regdump_len += ale_entries *
0548 ALE_ENTRY_WORDS * sizeof(u32);
0549 continue;
0550 }
0551 regdump_len += am65_cpsw_regdump[i].hdr.len;
0552 }
0553
0554 return regdump_len;
0555 }
0556
0557 static void am65_cpsw_get_regs(struct net_device *ndev,
0558 struct ethtool_regs *regs, void *p)
0559 {
0560 struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
0561 u32 ale_entries, i, j, pos, *reg = p;
0562
0563
0564 regs->version = AM65_CPSW_REGDUMP_VER;
0565 ale_entries = cpsw_ale_get_num_entries(common->ale);
0566
0567 pos = 0;
0568 for (i = 0; i < ARRAY_SIZE(am65_cpsw_regdump); i++) {
0569 reg[pos++] = am65_cpsw_regdump[i].hdr.module_id;
0570
0571 if (am65_cpsw_regdump[i].hdr.module_id ==
0572 AM65_CPSW_REGDUMP_MOD_CPSW_ALE_TBL) {
0573 u32 ale_tbl_len = ale_entries *
0574 ALE_ENTRY_WORDS * sizeof(u32) +
0575 sizeof(struct am65_cpsw_regdump_hdr);
0576 reg[pos++] = ale_tbl_len;
0577 cpsw_ale_dump(common->ale, ®[pos]);
0578 pos += ale_tbl_len;
0579 continue;
0580 }
0581
0582 reg[pos++] = am65_cpsw_regdump[i].hdr.len;
0583
0584 j = am65_cpsw_regdump[i].start_ofs;
0585 do {
0586 reg[pos++] = j;
0587 reg[pos++] = readl_relaxed(common->ss_base + j);
0588 j += sizeof(u32);
0589 } while (j <= am65_cpsw_regdump[i].end_ofs);
0590 }
0591 }
0592
0593 static int am65_cpsw_get_sset_count(struct net_device *ndev, int sset)
0594 {
0595 switch (sset) {
0596 case ETH_SS_STATS:
0597 return ARRAY_SIZE(am65_host_stats) +
0598 ARRAY_SIZE(am65_slave_stats);
0599 case ETH_SS_PRIV_FLAGS:
0600 return ARRAY_SIZE(am65_cpsw_ethtool_priv_flags);
0601 default:
0602 return -EOPNOTSUPP;
0603 }
0604 }
0605
0606 static void am65_cpsw_get_strings(struct net_device *ndev,
0607 u32 stringset, u8 *data)
0608 {
0609 const struct am65_cpsw_ethtool_stat *hw_stats;
0610 u32 i, num_stats;
0611 u8 *p = data;
0612
0613 switch (stringset) {
0614 case ETH_SS_STATS:
0615 num_stats = ARRAY_SIZE(am65_host_stats);
0616 hw_stats = am65_host_stats;
0617 for (i = 0; i < num_stats; i++) {
0618 memcpy(p, hw_stats[i].desc, ETH_GSTRING_LEN);
0619 p += ETH_GSTRING_LEN;
0620 }
0621
0622 num_stats = ARRAY_SIZE(am65_slave_stats);
0623 hw_stats = am65_slave_stats;
0624 for (i = 0; i < num_stats; i++) {
0625 memcpy(p, hw_stats[i].desc, ETH_GSTRING_LEN);
0626 p += ETH_GSTRING_LEN;
0627 }
0628 break;
0629 case ETH_SS_PRIV_FLAGS:
0630 num_stats = ARRAY_SIZE(am65_cpsw_ethtool_priv_flags);
0631
0632 for (i = 0; i < num_stats; i++) {
0633 memcpy(p, am65_cpsw_ethtool_priv_flags[i],
0634 ETH_GSTRING_LEN);
0635 p += ETH_GSTRING_LEN;
0636 }
0637 break;
0638 }
0639 }
0640
0641 static void am65_cpsw_get_ethtool_stats(struct net_device *ndev,
0642 struct ethtool_stats *stats, u64 *data)
0643 {
0644 struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
0645 const struct am65_cpsw_ethtool_stat *hw_stats;
0646 struct am65_cpsw_host *host_p;
0647 struct am65_cpsw_port *port;
0648 u32 i, num_stats;
0649
0650 host_p = am65_common_get_host(common);
0651 port = am65_ndev_to_port(ndev);
0652 num_stats = ARRAY_SIZE(am65_host_stats);
0653 hw_stats = am65_host_stats;
0654 for (i = 0; i < num_stats; i++)
0655 *data++ = readl_relaxed(host_p->stat_base +
0656 hw_stats[i].offset);
0657
0658 num_stats = ARRAY_SIZE(am65_slave_stats);
0659 hw_stats = am65_slave_stats;
0660 for (i = 0; i < num_stats; i++)
0661 *data++ = readl_relaxed(port->stat_base +
0662 hw_stats[i].offset);
0663 }
0664
0665 static int am65_cpsw_get_ethtool_ts_info(struct net_device *ndev,
0666 struct ethtool_ts_info *info)
0667 {
0668 struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
0669
0670 if (!IS_ENABLED(CONFIG_TI_K3_AM65_CPTS))
0671 return ethtool_op_get_ts_info(ndev, info);
0672
0673 info->so_timestamping =
0674 SOF_TIMESTAMPING_TX_HARDWARE |
0675 SOF_TIMESTAMPING_TX_SOFTWARE |
0676 SOF_TIMESTAMPING_RX_HARDWARE |
0677 SOF_TIMESTAMPING_RX_SOFTWARE |
0678 SOF_TIMESTAMPING_SOFTWARE |
0679 SOF_TIMESTAMPING_RAW_HARDWARE;
0680 info->phc_index = am65_cpts_phc_index(common->cpts);
0681 info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON);
0682 info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | BIT(HWTSTAMP_FILTER_ALL);
0683 return 0;
0684 }
0685
0686 static u32 am65_cpsw_get_ethtool_priv_flags(struct net_device *ndev)
0687 {
0688 struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
0689 u32 priv_flags = 0;
0690
0691 if (common->pf_p0_rx_ptype_rrobin)
0692 priv_flags |= AM65_CPSW_PRIV_P0_RX_PTYPE_RROBIN;
0693
0694 return priv_flags;
0695 }
0696
0697 static int am65_cpsw_set_ethtool_priv_flags(struct net_device *ndev, u32 flags)
0698 {
0699 struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
0700 int rrobin;
0701
0702 rrobin = !!(flags & AM65_CPSW_PRIV_P0_RX_PTYPE_RROBIN);
0703
0704 if (common->usage_count)
0705 return -EBUSY;
0706
0707 if (common->est_enabled && rrobin) {
0708 netdev_err(ndev,
0709 "p0-rx-ptype-rrobin flag conflicts with QOS\n");
0710 return -EINVAL;
0711 }
0712
0713 common->pf_p0_rx_ptype_rrobin = rrobin;
0714
0715 return 0;
0716 }
0717
0718 const struct ethtool_ops am65_cpsw_ethtool_ops_slave = {
0719 .begin = am65_cpsw_ethtool_op_begin,
0720 .complete = am65_cpsw_ethtool_op_complete,
0721 .get_drvinfo = am65_cpsw_get_drvinfo,
0722 .get_msglevel = am65_cpsw_get_msglevel,
0723 .set_msglevel = am65_cpsw_set_msglevel,
0724 .get_channels = am65_cpsw_get_channels,
0725 .set_channels = am65_cpsw_set_channels,
0726 .get_ringparam = am65_cpsw_get_ringparam,
0727 .get_regs_len = am65_cpsw_get_regs_len,
0728 .get_regs = am65_cpsw_get_regs,
0729 .get_sset_count = am65_cpsw_get_sset_count,
0730 .get_strings = am65_cpsw_get_strings,
0731 .get_ethtool_stats = am65_cpsw_get_ethtool_stats,
0732 .get_ts_info = am65_cpsw_get_ethtool_ts_info,
0733 .get_priv_flags = am65_cpsw_get_ethtool_priv_flags,
0734 .set_priv_flags = am65_cpsw_set_ethtool_priv_flags,
0735
0736 .get_link = ethtool_op_get_link,
0737 .get_link_ksettings = am65_cpsw_get_link_ksettings,
0738 .set_link_ksettings = am65_cpsw_set_link_ksettings,
0739 .get_pauseparam = am65_cpsw_get_pauseparam,
0740 .set_pauseparam = am65_cpsw_set_pauseparam,
0741 .get_wol = am65_cpsw_get_wol,
0742 .set_wol = am65_cpsw_set_wol,
0743 .get_eee = am65_cpsw_get_eee,
0744 .set_eee = am65_cpsw_set_eee,
0745 .nway_reset = am65_cpsw_nway_reset,
0746 };