@@ -405,22 +405,116 @@ static int mv88e6390_serdes_power_sgmii(struct mv88e6xxx_chip *chip, u8 lane,
405
405
return err ;
406
406
}
407
407
408
+ struct mv88e6390_serdes_hw_stat {
409
+ char string [ETH_GSTRING_LEN ];
410
+ int reg ;
411
+ };
412
+
413
+ static struct mv88e6390_serdes_hw_stat mv88e6390_serdes_hw_stats [] = {
414
+ { "serdes_rx_pkts" , 0xf021 },
415
+ { "serdes_rx_bytes" , 0xf024 },
416
+ { "serdes_rx_pkts_error" , 0xf027 },
417
+ };
418
+
419
+ int mv88e6390_serdes_get_sset_count (struct mv88e6xxx_chip * chip , int port )
420
+ {
421
+ if (mv88e6390_serdes_get_lane (chip , port ) == 0 )
422
+ return 0 ;
423
+
424
+ return ARRAY_SIZE (mv88e6390_serdes_hw_stats );
425
+ }
426
+
427
+ int mv88e6390_serdes_get_strings (struct mv88e6xxx_chip * chip ,
428
+ int port , uint8_t * data )
429
+ {
430
+ struct mv88e6390_serdes_hw_stat * stat ;
431
+ int i ;
432
+
433
+ if (mv88e6390_serdes_get_lane (chip , port ) == 0 )
434
+ return 0 ;
435
+
436
+ for (i = 0 ; i < ARRAY_SIZE (mv88e6390_serdes_hw_stats ); i ++ ) {
437
+ stat = & mv88e6390_serdes_hw_stats [i ];
438
+ memcpy (data + i * ETH_GSTRING_LEN , stat -> string ,
439
+ ETH_GSTRING_LEN );
440
+ }
441
+ return ARRAY_SIZE (mv88e6390_serdes_hw_stats );
442
+ }
443
+
444
+ static uint64_t mv88e6390_serdes_get_stat (struct mv88e6xxx_chip * chip , int lane ,
445
+ struct mv88e6390_serdes_hw_stat * stat )
446
+ {
447
+ u16 reg [3 ];
448
+ int err , i ;
449
+
450
+ for (i = 0 ; i < 3 ; i ++ ) {
451
+ err = mv88e6390_serdes_read (chip , lane , MDIO_MMD_PHYXS ,
452
+ stat -> reg + i , & reg [i ]);
453
+ if (err ) {
454
+ dev_err (chip -> dev , "failed to read statistic\n" );
455
+ return 0 ;
456
+ }
457
+ }
458
+
459
+ return reg [0 ] | ((u64 )reg [1 ] << 16 ) | ((u64 )reg [2 ] << 32 );
460
+ }
461
+
462
+ int mv88e6390_serdes_get_stats (struct mv88e6xxx_chip * chip , int port ,
463
+ uint64_t * data )
464
+ {
465
+ struct mv88e6390_serdes_hw_stat * stat ;
466
+ int lane ;
467
+ int i ;
468
+
469
+ lane = mv88e6390_serdes_get_lane (chip , port );
470
+ if (lane == 0 )
471
+ return 0 ;
472
+
473
+ for (i = 0 ; i < ARRAY_SIZE (mv88e6390_serdes_hw_stats ); i ++ ) {
474
+ stat = & mv88e6390_serdes_hw_stats [i ];
475
+ data [i ] = mv88e6390_serdes_get_stat (chip , lane , stat );
476
+ }
477
+
478
+ return ARRAY_SIZE (mv88e6390_serdes_hw_stats );
479
+ }
480
+
481
+ static int mv88e6390_serdes_enable_checker (struct mv88e6xxx_chip * chip , u8 lane )
482
+ {
483
+ u16 reg ;
484
+ int err ;
485
+
486
+ err = mv88e6390_serdes_read (chip , lane , MDIO_MMD_PHYXS ,
487
+ MV88E6390_PG_CONTROL , & reg );
488
+ if (err )
489
+ return err ;
490
+
491
+ reg |= MV88E6390_PG_CONTROL_ENABLE_PC ;
492
+ return mv88e6390_serdes_write (chip , lane , MDIO_MMD_PHYXS ,
493
+ MV88E6390_PG_CONTROL , reg );
494
+ }
495
+
408
496
int mv88e6390_serdes_power (struct mv88e6xxx_chip * chip , int port , u8 lane ,
409
497
bool up )
410
498
{
411
499
u8 cmode = chip -> ports [port ].cmode ;
500
+ int err = 0 ;
412
501
413
502
switch (cmode ) {
414
503
case MV88E6XXX_PORT_STS_CMODE_SGMII :
415
504
case MV88E6XXX_PORT_STS_CMODE_1000BASEX :
416
505
case MV88E6XXX_PORT_STS_CMODE_2500BASEX :
417
- return mv88e6390_serdes_power_sgmii (chip , lane , up );
506
+ err = mv88e6390_serdes_power_sgmii (chip , lane , up );
507
+ break ;
418
508
case MV88E6XXX_PORT_STS_CMODE_XAUI :
419
509
case MV88E6XXX_PORT_STS_CMODE_RXAUI :
420
- return mv88e6390_serdes_power_10g (chip , lane , up );
510
+ err = mv88e6390_serdes_power_10g (chip , lane , up );
511
+ break ;
421
512
}
422
513
423
- return 0 ;
514
+ if (!err && up )
515
+ err = mv88e6390_serdes_enable_checker (chip , lane );
516
+
517
+ return err ;
424
518
}
425
519
426
520
static void mv88e6390_serdes_irq_link_sgmii (struct mv88e6xxx_chip * chip ,
0 commit comments