@@ -157,6 +157,7 @@ uint32_t phy_detected[ 4 ];
157157#define PHY_MARVELL_IDENTIFIER 0x0141
158158#define PHY_TI_IDENTIFIER 0x2000
159159#define PHY_REALTEK_IDENTIFIER 0x001c
160+ #define PHY_MICREL_IDENTIFIER 0x0022
160161#define PHY_AR8035_IDENTIFIER 0x004D
161162#define PHY_XILINX_PCS_PMA_ID1 0x0174
162163#define PHY_XILINX_PCS_PMA_ID2 0x0C00
@@ -659,6 +660,240 @@ static uint32_t get_Realtek_phy_speed( XEmacPs * xemacpsp,
659660 return XST_FAILURE ;
660661}
661662
663+ #define LPA_IEEE_1000FD 0x0800
664+ #define LP5_IEEE_100BTXFD 0x0100
665+ #define LP5_IEEE_10BTFD 0x0040
666+ #define MICREL_ID_KSZ9021 0x0161
667+ #define MICREL_ID_KSZ9031 0x0162
668+ #define MICREL_ID_KSZ9131 0x0164
669+
670+
671+ static int set_Micrel_phy_delays ( XEmacPs * EmacPsInstancePtr ,
672+ uint32_t PhyAddr )
673+ {
674+ int Status ;
675+ uint16_t PhyType , PhyData ;
676+
677+ XEmacPs_PhyRead ( EmacPsInstancePtr , PhyAddr , 0x3 , ( u16 * ) & PhyData ); /* read value */
678+ PhyType = ( PhyData >> 4 );
679+
680+ /* enabling RGMII delays */
681+ if ( PhyType == MICREL_ID_KSZ9131 ) /* KSZ9131 */
682+ {
683+ FreeRTOS_printf ( ( "Detected KSZ9131 Ethernet PHY\n\r" ) );
684+ /*Ctrl Delay */
685+ u16 RxCtrlDelay = 7 ; /* 0..15, default 7 */
686+ u16 TxCtrlDelay = 7 ; /* 0..15, default 7 */
687+ XEmacPs_PhyWrite ( EmacPsInstancePtr , PhyAddr , 0xD , 0x0002 );
688+ XEmacPs_PhyWrite ( EmacPsInstancePtr , PhyAddr , 0xE , 0x0004 ); /* Reg 0x4 */
689+ XEmacPs_PhyWrite ( EmacPsInstancePtr , PhyAddr , 0xD , 0x4002 );
690+ XEmacPs_PhyWrite ( EmacPsInstancePtr , PhyAddr , 0xE , ( TxCtrlDelay | ( RxCtrlDelay << 4 ) ) );
691+ /*Data Delay */
692+ u16 RxDataDelay = 7 ; /* 0..15, default 7 */
693+ u16 TxDataDelay = 7 ; /* 0..15, default 7 */
694+ XEmacPs_PhyWrite ( EmacPsInstancePtr , PhyAddr , 0xD , 0x0002 );
695+ XEmacPs_PhyWrite ( EmacPsInstancePtr , PhyAddr , 0xE , 0x0005 ); /* Reg 0x5 */
696+ XEmacPs_PhyWrite ( EmacPsInstancePtr , PhyAddr , 0xD , 0x4002 );
697+ XEmacPs_PhyWrite ( EmacPsInstancePtr , PhyAddr , 0xE , ( RxDataDelay | ( RxDataDelay << 4 ) | ( RxDataDelay << 8 ) | ( RxDataDelay << 12 ) ) );
698+ XEmacPs_PhyWrite ( EmacPsInstancePtr , PhyAddr , 0xD , 0x0002 );
699+ XEmacPs_PhyWrite ( EmacPsInstancePtr , PhyAddr , 0xE , 0x0006 ); /* Reg 0x6 */
700+ XEmacPs_PhyWrite ( EmacPsInstancePtr , PhyAddr , 0xD , 0x4002 );
701+ XEmacPs_PhyWrite ( EmacPsInstancePtr , PhyAddr , 0xE , ( TxDataDelay | ( TxDataDelay << 4 ) | ( TxDataDelay << 8 ) | ( TxDataDelay << 12 ) ) );
702+ /*Clock Delay */
703+ u16 RxClockDelay = 31 ; /* 0..31, default 15 */
704+ u16 TxClockDelay = 31 ; /* 0..31, default 15 */
705+ XEmacPs_PhyWrite ( EmacPsInstancePtr , PhyAddr , 0xD , 0x0002 );
706+ XEmacPs_PhyWrite ( EmacPsInstancePtr , PhyAddr , 0xE , 0x0008 ); /* Reg 0x8 RGMII Clock Pad Skew */
707+ XEmacPs_PhyWrite ( EmacPsInstancePtr , PhyAddr , 0xD , 0x4002 );
708+ XEmacPs_PhyWrite ( EmacPsInstancePtr , PhyAddr , 0xE , ( RxClockDelay | ( TxClockDelay << 5 ) ) );
709+ }
710+ else if ( PhyType == MICREL_ID_KSZ9031 ) /* KSZ9031 */
711+ {
712+ FreeRTOS_printf ( ( "Detected KSZ9031 Ethernet PHY\n\r" ) );
713+ /*Ctrl Delay */
714+ u16 RxCtrlDelay = 7 ; /* 0..15, default 7 */
715+ u16 TxCtrlDelay = 7 ; /* 0..15, default 7 */
716+ XEmacPs_PhyWrite ( EmacPsInstancePtr , PhyAddr , 0xD , 0x0002 );
717+ XEmacPs_PhyWrite ( EmacPsInstancePtr , PhyAddr , 0xE , 0x0004 ); /* Reg 0x4 */
718+ XEmacPs_PhyWrite ( EmacPsInstancePtr , PhyAddr , 0xD , 0x4002 );
719+ XEmacPs_PhyWrite ( EmacPsInstancePtr , PhyAddr , 0xE , ( TxCtrlDelay | ( RxCtrlDelay << 4 ) ) );
720+ /*Data Delay */
721+ u16 RxDataDelay = 7 ; /* 0..15, default 7 */
722+ u16 TxDataDelay = 7 ; /* 0..15, default 7 */
723+ XEmacPs_PhyWrite ( EmacPsInstancePtr , PhyAddr , 0xD , 0x0002 );
724+ XEmacPs_PhyWrite ( EmacPsInstancePtr , PhyAddr , 0xE , 0x0005 ); /* Reg 0x5 */
725+ XEmacPs_PhyWrite ( EmacPsInstancePtr , PhyAddr , 0xD , 0x4002 );
726+ XEmacPs_PhyWrite ( EmacPsInstancePtr , PhyAddr , 0xE , ( RxDataDelay | ( RxDataDelay << 4 ) | ( RxDataDelay << 8 ) | ( RxDataDelay << 12 ) ) );
727+ XEmacPs_PhyWrite ( EmacPsInstancePtr , PhyAddr , 0xD , 0x0002 );
728+ XEmacPs_PhyWrite ( EmacPsInstancePtr , PhyAddr , 0xE , 0x0006 ); /* Reg 0x6 */
729+ XEmacPs_PhyWrite ( EmacPsInstancePtr , PhyAddr , 0xD , 0x4002 );
730+ XEmacPs_PhyWrite ( EmacPsInstancePtr , PhyAddr , 0xE , ( TxDataDelay | ( TxDataDelay << 4 ) | ( TxDataDelay << 8 ) | ( TxDataDelay << 12 ) ) );
731+ /*Clock Delay */
732+ u16 RxClockDelay = 31 ; /* 0..31, default 15 */
733+ u16 TxClockDelay = 31 ; /* 0..31, default 15 */
734+ XEmacPs_PhyWrite ( EmacPsInstancePtr , PhyAddr , 0xD , 0x0002 );
735+ XEmacPs_PhyWrite ( EmacPsInstancePtr , PhyAddr , 0xE , 0x0008 ); /* Reg 0x8 RGMII Clock Pad Skew */
736+ XEmacPs_PhyWrite ( EmacPsInstancePtr , PhyAddr , 0xD , 0x4002 );
737+ XEmacPs_PhyWrite ( EmacPsInstancePtr , PhyAddr , 0xE , ( RxClockDelay | ( TxClockDelay << 5 ) ) );
738+ }
739+ else if ( PhyType == MICREL_ID_KSZ9021 ) /* KSZ9021 */
740+ {
741+ FreeRTOS_printf ( ( "Detected KSZ9021 Ethernet PHY\n\r" ) );
742+ XEmacPs_PhyWrite ( EmacPsInstancePtr , PhyAddr , 0xB , 0x8104 ); /* write Reg 0x104 */
743+ XEmacPs_PhyWrite ( EmacPsInstancePtr , PhyAddr , 0xC , 0xF0F0 ); /* set write data */
744+ XEmacPs_PhyWrite ( EmacPsInstancePtr , PhyAddr , 0xB , 0x8105 ); /* write Reg 0x105 */
745+ XEmacPs_PhyWrite ( EmacPsInstancePtr , PhyAddr , 0xC , 0x0000 ); /* set write data */
746+ }
747+
748+ /* Issue a reset to phy */
749+ Status = XEmacPs_PhyRead ( EmacPsInstancePtr , PhyAddr , 0x0 , & PhyData );
750+ PhyData |= 0x8000 ;
751+ Status = XEmacPs_PhyWrite ( EmacPsInstancePtr , PhyAddr , 0x0 , PhyData );
752+ vTaskDelay ( 1 );
753+ Status |= XEmacPs_PhyRead ( EmacPsInstancePtr , PhyAddr , 0x0 , & PhyData );
754+
755+ if ( Status != XST_SUCCESS )
756+ {
757+ return Status ;
758+ }
759+
760+ return PhyType ;
761+ }
762+
763+ static uint32_t get_Micrel_phy_speed ( XEmacPs * xemacpsp ,
764+ uint32_t phy_addr )
765+ {
766+ const char * name_ptr ;
767+ uint16_t temp , phy_type ;
768+ uint16_t control ;
769+ uint16_t status ;
770+ uint16_t status_speed ;
771+ uint32_t timeout_counter = 0 ;
772+
773+ /* Just to prevent compiler warnings about unused variables. */
774+ ( void ) name_ptr ;
775+
776+
777+ FreeRTOS_printf ( ( "Start Micrel PHY program delay\r\n" ) );
778+
779+ if ( ( phy_type = set_Micrel_phy_delays ( xemacpsp , phy_addr ) ) != XST_FAILURE )
780+ {
781+ FreeRTOS_printf ( ( "Delay Set Okay!\r\n" ) );
782+ }
783+ else
784+ {
785+ FreeRTOS_printf ( ( "Delay Set Error!\r\n" ) );
786+ }
787+
788+ switch ( phy_type )
789+ {
790+ case MICREL_ID_KSZ9021 :
791+ name_ptr = "KSZ9021" ;
792+ break ;
793+
794+ case MICREL_ID_KSZ9031 :
795+ name_ptr = "KSZ9031" ;
796+ break ;
797+
798+ case MICREL_ID_KSZ9131 :
799+ name_ptr = "KSZ9131" ;
800+ break ;
801+
802+ default :
803+ name_ptr = "!UNKNOWN!" ;
804+ break ;
805+ }
806+
807+ FreeRTOS_printf ( ( "Start %s auto-negotiation\r\n" , name_ptr ) );
808+
809+ XEmacPs_PhyRead ( xemacpsp , phy_addr , IEEE_AUTONEGO_ADVERTISE_REG , & control );
810+ control |= IEEE_ASYMMETRIC_PAUSE_MASK ;
811+ control |= IEEE_PAUSE_MASK ;
812+ control |= ADVERTISE_100 ;
813+ control |= ADVERTISE_10 ;
814+ XEmacPs_PhyWrite ( xemacpsp , phy_addr , IEEE_AUTONEGO_ADVERTISE_REG , control );
815+
816+ XEmacPs_PhyRead ( xemacpsp , phy_addr , IEEE_1000_ADVERTISE_REG_OFFSET , & control );
817+ control |= ADVERTISE_1000 ;
818+ XEmacPs_PhyWrite ( xemacpsp , phy_addr , IEEE_1000_ADVERTISE_REG_OFFSET , control );
819+
820+ XEmacPs_PhyRead ( xemacpsp , phy_addr , IEEE_COPPER_SPECIFIC_CONTROL_REG , & control );
821+ control |= ( 7 << 12 );
822+ control |= ( 1 << 11 );
823+ XEmacPs_PhyWrite ( xemacpsp , phy_addr , IEEE_COPPER_SPECIFIC_CONTROL_REG , control );
824+
825+ XEmacPs_PhyRead ( xemacpsp , phy_addr , IEEE_CONTROL_REG_OFFSET , & control );
826+ control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE ;
827+ control |= IEEE_STAT_AUTONEGOTIATE_RESTART ;
828+ XEmacPs_PhyWrite ( xemacpsp , phy_addr , IEEE_CONTROL_REG_OFFSET , control );
829+
830+ XEmacPs_PhyRead ( xemacpsp , phy_addr , IEEE_CONTROL_REG_OFFSET , & control );
831+ control |= IEEE_CTRL_RESET_MASK ;
832+ XEmacPs_PhyWrite ( xemacpsp , phy_addr , IEEE_CONTROL_REG_OFFSET , control );
833+
834+ while ( 1 )
835+ {
836+ XEmacPs_PhyRead ( xemacpsp , phy_addr , IEEE_CONTROL_REG_OFFSET , & control );
837+
838+ if ( control & IEEE_CTRL_RESET_MASK )
839+ {
840+ continue ;
841+ }
842+ else
843+ {
844+ break ;
845+ }
846+ }
847+
848+ XEmacPs_PhyRead ( xemacpsp , phy_addr , IEEE_STATUS_REG_OFFSET , & status );
849+
850+ FreeRTOS_printf ( ( "Waiting for %s to complete Auto-negotiation.\r\n" , name_ptr ) );
851+
852+ while ( !( status & IEEE_STAT_AUTONEGOTIATE_COMPLETE ) )
853+ {
854+ vTaskDelay ( pdMS_TO_TICKS ( 1000 ) );
855+ XEmacPs_PhyRead ( xemacpsp , phy_addr , IEEE_COPPER_SPECIFIC_STATUS_REG_2 , & temp );
856+ timeout_counter ++ ;
857+
858+ if ( timeout_counter == 30 )
859+ {
860+ FreeRTOS_printf ( ( "Auto negotiation error \r\n" ) );
861+ return XST_FAILURE ;
862+ }
863+
864+ XEmacPs_PhyRead ( xemacpsp , phy_addr , IEEE_STATUS_REG_OFFSET , & status );
865+ }
866+
867+ FreeRTOS_printf ( ( "%s Completed Auto-negotiation\r\n" , name_ptr ) );
868+
869+ /* Check for high speed connection first */
870+ XEmacPs_PhyRead ( xemacpsp , phy_addr , IEEE_PARTNER_ABILITIES_3_REG_OFFSET , & status_speed );
871+
872+ if ( status_speed & LPA_IEEE_1000FD )
873+ {
874+ FreeRTOS_printf ( ( "Micrel PHY %s speed 1000Mbps\r\n" , name_ptr ) );
875+ return 1000 ;
876+ }
877+ else /* No high speed so check lows... */
878+ {
879+ XEmacPs_PhyRead ( xemacpsp , phy_addr , IEEE_PARTNER_ABILITIES_1_REG_OFFSET , & status_speed );
880+
881+ if ( status_speed & LP5_IEEE_100BTXFD )
882+ {
883+ FreeRTOS_printf ( ( "Micrel PHY %s speed 100Mbps\r\n" , name_ptr ) );
884+ return 100 ;
885+ }
886+
887+ if ( status_speed & LP5_IEEE_10BTFD )
888+ {
889+ FreeRTOS_printf ( ( "Micrel PHY %s speed 10Mbps\r\n" , name_ptr ) );
890+ return 10 ;
891+ }
892+ }
893+
894+ return XST_FAILURE ;
895+ }
896+
662897/* Here is a XEmacPs_PhyRead() that returns the value of a register. */
663898static uint16_t XEmacPs_PhyRead2 ( XEmacPs * InstancePtr ,
664899 u32 PhyAddress ,
@@ -898,6 +1133,10 @@ static const char * pcGetPHIName( uint16_t usID )
8981133 pcReturn = "Realtek RTL8212" ;
8991134 break ;
9001135
1136+ case PHY_MICREL_IDENTIFIER :
1137+ pcReturn = "MICREL PHY" ;
1138+ break ;
1139+
9011140 case PHY_AR8035_IDENTIFIER :
9021141 pcReturn = "Atheros_ar8035" ;
9031142 break ;
@@ -945,6 +1184,10 @@ static uint32_t get_IEEE_phy_speed_US( XEmacPs * xemacpsp,
9451184 RetStatus = get_Marvell_phy_speed ( xemacpsp , phy_addr );
9461185 break ;
9471186
1187+ case PHY_MICREL_IDENTIFIER :
1188+ RetStatus = get_Micrel_phy_speed ( xemacpsp , phy_addr );
1189+ break ;
1190+
9481191 case PHY_AR8035_IDENTIFIER :
9491192 RetStatus = get_AR8035_phy_speed ( xemacpsp , phy_addr );
9501193 prvSET_AR803x_TX_Timing ( xemacpsp , phy_addr );
0 commit comments