Merge branch 'next'

This brings in the u-boot-net PR from Joe.
diff --git a/arch/arm/dts/ast2500-evb.dts b/arch/arm/dts/ast2500-evb.dts
index 723941a..ebf44fd 100644
--- a/arch/arm/dts/ast2500-evb.dts
+++ b/arch/arm/dts/ast2500-evb.dts
@@ -11,6 +11,11 @@
 	chosen {
 		stdout-path = &uart5;
 	};
+
+	aliases {
+		ethernet0 = &mac0;
+		ethernet1 = &mac1;
+	};
 };
 
 &uart5 {
@@ -36,3 +41,21 @@
 	u-boot,dm-pre-reloc;
 	status = "okay";
 };
+
+&mac0 {
+	status = "okay";
+
+	phy-mode = "rgmii";
+
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_mac1link_default &pinctrl_mdio1_default>;
+};
+
+&mac1 {
+	status = "okay";
+
+	phy-mode = "rgmii";
+
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_mac2link_default &pinctrl_mdio2_default>;
+};
diff --git a/arch/arm/dts/ast2500.dtsi b/arch/arm/dts/ast2500.dtsi
index 7e0ad3a..98359bf 100644
--- a/arch/arm/dts/ast2500.dtsi
+++ b/arch/arm/dts/ast2500.dtsi
@@ -11,6 +11,29 @@
 	#size-cells = <1>;
 	interrupt-parent = <&vic>;
 
+	aliases {
+		i2c0 = &i2c0;
+		i2c1 = &i2c1;
+		i2c2 = &i2c2;
+		i2c3 = &i2c3;
+		i2c4 = &i2c4;
+		i2c5 = &i2c5;
+		i2c6 = &i2c6;
+		i2c7 = &i2c7;
+		i2c8 = &i2c8;
+		i2c9 = &i2c9;
+		i2c10 = &i2c10;
+		i2c11 = &i2c11;
+		i2c12 = &i2c12;
+		i2c13 = &i2c13;
+		serial0 = &uart1;
+		serial1 = &uart2;
+		serial2 = &uart3;
+		serial3 = &uart4;
+		serial4 = &uart5;
+		serial5 = &vuart;
+	};
+
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -22,12 +45,80 @@
 		};
 	};
 
+	memory@80000000 {
+		device_type = "memory";
+		reg = <0x80000000 0>;
+	};
+
 	ahb {
 		compatible = "simple-bus";
 		#address-cells = <1>;
 		#size-cells = <1>;
 		ranges;
 
+		fmc: flash-controller@1e620000 {
+			reg = < 0x1e620000 0xc4
+				0x20000000 0x10000000 >;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "aspeed,ast2500-fmc";
+			status = "disabled";
+			interrupts = <19>;
+			flash@0 {
+				reg = < 0 >;
+				compatible = "jedec,spi-nor";
+				status = "disabled";
+			};
+			flash@1 {
+				reg = < 1 >;
+				compatible = "jedec,spi-nor";
+				status = "disabled";
+			};
+			flash@2 {
+				reg = < 2 >;
+				compatible = "jedec,spi-nor";
+				status = "disabled";
+			};
+		};
+
+		spi1: flash-controller@1e630000 {
+			reg = < 0x1e630000 0xc4
+				0x30000000 0x08000000 >;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "aspeed,ast2500-spi";
+			status = "disabled";
+			flash@0 {
+				reg = < 0 >;
+				compatible = "jedec,spi-nor";
+				status = "disabled";
+			};
+			flash@1 {
+				reg = < 1 >;
+				compatible = "jedec,spi-nor";
+				status = "disabled";
+			};
+		};
+
+		spi2: flash-controller@1e631000 {
+			reg = < 0x1e631000 0xc4
+				0x38000000 0x08000000 >;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "aspeed,ast2500-spi";
+			status = "disabled";
+			flash@0 {
+				reg = < 0 >;
+				compatible = "jedec,spi-nor";
+				status = "disabled";
+			};
+			flash@1 {
+				reg = < 1 >;
+				compatible = "jedec,spi-nor";
+				status = "disabled";
+			};
+		};
+
 		vic: interrupt-controller@1e6c0080 {
 			compatible = "aspeed,ast2400-vic";
 			interrupt-controller;
@@ -37,18 +128,38 @@
 		};
 
 		mac0: ethernet@1e660000 {
-			compatible = "faraday,ftgmac100";
+			compatible = "aspeed,ast2500-mac", "faraday,ftgmac100";
 			reg = <0x1e660000 0x180>;
 			interrupts = <2>;
-			no-hw-checksum;
 			status = "disabled";
 		};
 
 		mac1: ethernet@1e680000 {
-			compatible = "faraday,ftgmac100";
+			compatible = "aspeed,ast2500-mac", "faraday,ftgmac100";
 			reg = <0x1e680000 0x180>;
 			interrupts = <3>;
-			no-hw-checksum;
+			status = "disabled";
+		};
+
+		ehci0: usb@1e6a1000 {
+			compatible = "aspeed,ast2500-ehci", "generic-ehci";
+			reg = <0x1e6a1000 0x100>;
+			interrupts = <5>;
+			status = "disabled";
+		};
+
+		ehci1: usb@1e6a3000 {
+			compatible = "aspeed,ast2500-ehci", "generic-ehci";
+			reg = <0x1e6a3000 0x100>;
+			interrupts = <13>;
+			status = "disabled";
+		};
+
+		uhci: usb@1e6b0000 {
+			compatible = "aspeed,ast2500-uhci", "generic-uhci";
+			reg = <0x1e6b0000 0x100>;
+			interrupts = <14>;
+			#ports = <2>;
 			status = "disabled";
 		};
 
@@ -58,853 +169,24 @@
 			#size-cells = <1>;
 			ranges;
 
-			clk_clkin: clk_clkin@1e6e2070 {
-				#clock-cells = <0>;
-				compatible = "aspeed,g5-clkin-clock";
-				reg = <0x1e6e2070 0x04>;
-			};
-
 			syscon: syscon@1e6e2000 {
 				compatible = "aspeed,g5-scu", "syscon", "simple-mfd";
 				reg = <0x1e6e2000 0x1a8>;
+				#clock-cells = <1>;
+				#reset-cells = <1>;
 
 				pinctrl: pinctrl {
 					compatible = "aspeed,g5-pinctrl";
 					aspeed,external-nodes = <&gfx &lhc>;
 
-					pinctrl_acpi_default: acpi_default {
-						function = "ACPI";
-						groups = "ACPI";
-					};
-
-					pinctrl_adc0_default: adc0_default {
-						function = "ADC0";
-						groups = "ADC0";
-					};
-
-					pinctrl_adc1_default: adc1_default {
-						function = "ADC1";
-						groups = "ADC1";
-					};
-
-					pinctrl_adc10_default: adc10_default {
-						function = "ADC10";
-						groups = "ADC10";
-					};
-
-					pinctrl_adc11_default: adc11_default {
-						function = "ADC11";
-						groups = "ADC11";
-					};
-
-					pinctrl_adc12_default: adc12_default {
-						function = "ADC12";
-						groups = "ADC12";
-					};
-
-					pinctrl_adc13_default: adc13_default {
-						function = "ADC13";
-						groups = "ADC13";
-					};
-
-					pinctrl_adc14_default: adc14_default {
-						function = "ADC14";
-						groups = "ADC14";
-					};
-
-					pinctrl_adc15_default: adc15_default {
-						function = "ADC15";
-						groups = "ADC15";
-					};
-
-					pinctrl_adc2_default: adc2_default {
-						function = "ADC2";
-						groups = "ADC2";
-					};
-
-					pinctrl_adc3_default: adc3_default {
-						function = "ADC3";
-						groups = "ADC3";
-					};
-
-					pinctrl_adc4_default: adc4_default {
-						function = "ADC4";
-						groups = "ADC4";
-					};
-
-					pinctrl_adc5_default: adc5_default {
-						function = "ADC5";
-						groups = "ADC5";
-					};
-
-					pinctrl_adc6_default: adc6_default {
-						function = "ADC6";
-						groups = "ADC6";
-					};
-
-					pinctrl_adc7_default: adc7_default {
-						function = "ADC7";
-						groups = "ADC7";
-					};
-
-					pinctrl_adc8_default: adc8_default {
-						function = "ADC8";
-						groups = "ADC8";
-					};
-
-					pinctrl_adc9_default: adc9_default {
-						function = "ADC9";
-						groups = "ADC9";
-					};
-
-					pinctrl_bmcint_default: bmcint_default {
-						function = "BMCINT";
-						groups = "BMCINT";
-					};
-
-					pinctrl_ddcclk_default: ddcclk_default {
-						function = "DDCCLK";
-						groups = "DDCCLK";
-					};
-
-					pinctrl_ddcdat_default: ddcdat_default {
-						function = "DDCDAT";
-						groups = "DDCDAT";
-					};
-
-					pinctrl_espi_default: espi_default {
-						function = "ESPI";
-						groups = "ESPI";
-					};
-
-					pinctrl_fwspics1_default: fwspics1_default {
-						function = "FWSPICS1";
-						groups = "FWSPICS1";
-					};
-
-					pinctrl_fwspics2_default: fwspics2_default {
-						function = "FWSPICS2";
-						groups = "FWSPICS2";
-					};
-
-					pinctrl_gpid0_default: gpid0_default {
-						function = "GPID0";
-						groups = "GPID0";
-					};
-
-					pinctrl_gpid2_default: gpid2_default {
-						function = "GPID2";
-						groups = "GPID2";
-					};
-
-					pinctrl_gpid4_default: gpid4_default {
-						function = "GPID4";
-						groups = "GPID4";
-					};
-
-					pinctrl_gpid6_default: gpid6_default {
-						function = "GPID6";
-						groups = "GPID6";
-					};
-
-					pinctrl_gpie0_default: gpie0_default {
-						function = "GPIE0";
-						groups = "GPIE0";
-					};
-
-					pinctrl_gpie2_default: gpie2_default {
-						function = "GPIE2";
-						groups = "GPIE2";
-					};
-
-					pinctrl_gpie4_default: gpie4_default {
-						function = "GPIE4";
-						groups = "GPIE4";
-					};
-
-					pinctrl_gpie6_default: gpie6_default {
-						function = "GPIE6";
-						groups = "GPIE6";
-					};
-
-					pinctrl_i2c10_default: i2c10_default {
-						function = "I2C10";
-						groups = "I2C10";
-					};
-
-					pinctrl_i2c11_default: i2c11_default {
-						function = "I2C11";
-						groups = "I2C11";
-					};
-
-					pinctrl_i2c12_default: i2c12_default {
-						function = "I2C12";
-						groups = "I2C12";
-					};
-
-					pinctrl_i2c13_default: i2c13_default {
-						function = "I2C13";
-						groups = "I2C13";
-					};
-
-					pinctrl_i2c14_default: i2c14_default {
-						function = "I2C14";
-						groups = "I2C14";
-					};
-
-					pinctrl_i2c3_default: i2c3_default {
-						function = "I2C3";
-						groups = "I2C3";
-					};
-
-					pinctrl_i2c4_default: i2c4_default {
-						function = "I2C4";
-						groups = "I2C4";
-					};
-
-					pinctrl_i2c5_default: i2c5_default {
-						function = "I2C5";
-						groups = "I2C5";
-					};
-
-					pinctrl_i2c6_default: i2c6_default {
-						function = "I2C6";
-						groups = "I2C6";
-					};
-
-					pinctrl_i2c7_default: i2c7_default {
-						function = "I2C7";
-						groups = "I2C7";
-					};
-
-					pinctrl_i2c8_default: i2c8_default {
-						function = "I2C8";
-						groups = "I2C8";
-					};
-
-					pinctrl_i2c9_default: i2c9_default {
-						function = "I2C9";
-						groups = "I2C9";
-					};
-
-					pinctrl_lad0_default: lad0_default {
-						function = "LAD0";
-						groups = "LAD0";
-					};
-
-					pinctrl_lad1_default: lad1_default {
-						function = "LAD1";
-						groups = "LAD1";
-					};
-
-					pinctrl_lad2_default: lad2_default {
-						function = "LAD2";
-						groups = "LAD2";
-					};
-
-					pinctrl_lad3_default: lad3_default {
-						function = "LAD3";
-						groups = "LAD3";
-					};
-
-					pinctrl_lclk_default: lclk_default {
-						function = "LCLK";
-						groups = "LCLK";
-					};
-
-					pinctrl_lframe_default: lframe_default {
-						function = "LFRAME";
-						groups = "LFRAME";
-					};
-
-					pinctrl_lpchc_default: lpchc_default {
-						function = "LPCHC";
-						groups = "LPCHC";
-					};
-
-					pinctrl_lpcpd_default: lpcpd_default {
-						function = "LPCPD";
-						groups = "LPCPD";
-					};
-
-					pinctrl_lpcplus_default: lpcplus_default {
-						function = "LPCPLUS";
-						groups = "LPCPLUS";
-					};
-
-					pinctrl_lpcpme_default: lpcpme_default {
-						function = "LPCPME";
-						groups = "LPCPME";
-					};
-
-					pinctrl_lpcrst_default: lpcrst_default {
-						function = "LPCRST";
-						groups = "LPCRST";
-					};
-
-					pinctrl_lpcsmi_default: lpcsmi_default {
-						function = "LPCSMI";
-						groups = "LPCSMI";
-					};
-
-					pinctrl_lsirq_default: lsirq_default {
-						function = "LSIRQ";
-						groups = "LSIRQ";
-					};
-
-					pinctrl_mac1link_default: mac1link_default {
-						function = "MAC1LINK";
-						groups = "MAC1LINK";
-					};
-
-					pinctrl_mac2link_default: mac2link_default {
-						function = "MAC2LINK";
-						groups = "MAC2LINK";
-					};
-
-					pinctrl_mdio1_default: mdio1_default {
-						function = "MDIO1";
-						groups = "MDIO1";
-					};
-
-					pinctrl_mdio2_default: mdio2_default {
-						function = "MDIO2";
-						groups = "MDIO2";
-					};
-
-					pinctrl_ncts1_default: ncts1_default {
-						function = "NCTS1";
-						groups = "NCTS1";
-					};
-
-					pinctrl_ncts2_default: ncts2_default {
-						function = "NCTS2";
-						groups = "NCTS2";
-					};
-
-					pinctrl_ncts3_default: ncts3_default {
-						function = "NCTS3";
-						groups = "NCTS3";
-					};
-
-					pinctrl_ncts4_default: ncts4_default {
-						function = "NCTS4";
-						groups = "NCTS4";
-					};
-
-					pinctrl_ndcd1_default: ndcd1_default {
-						function = "NDCD1";
-						groups = "NDCD1";
-					};
-
-					pinctrl_ndcd2_default: ndcd2_default {
-						function = "NDCD2";
-						groups = "NDCD2";
-					};
-
-					pinctrl_ndcd3_default: ndcd3_default {
-						function = "NDCD3";
-						groups = "NDCD3";
-					};
-
-					pinctrl_ndcd4_default: ndcd4_default {
-						function = "NDCD4";
-						groups = "NDCD4";
-					};
-
-					pinctrl_ndsr1_default: ndsr1_default {
-						function = "NDSR1";
-						groups = "NDSR1";
-					};
-
-					pinctrl_ndsr2_default: ndsr2_default {
-						function = "NDSR2";
-						groups = "NDSR2";
-					};
-
-					pinctrl_ndsr3_default: ndsr3_default {
-						function = "NDSR3";
-						groups = "NDSR3";
-					};
-
-					pinctrl_ndsr4_default: ndsr4_default {
-						function = "NDSR4";
-						groups = "NDSR4";
-					};
-
-					pinctrl_ndtr1_default: ndtr1_default {
-						function = "NDTR1";
-						groups = "NDTR1";
-					};
-
-					pinctrl_ndtr2_default: ndtr2_default {
-						function = "NDTR2";
-						groups = "NDTR2";
-					};
-
-					pinctrl_ndtr3_default: ndtr3_default {
-						function = "NDTR3";
-						groups = "NDTR3";
-					};
-
-					pinctrl_ndtr4_default: ndtr4_default {
-						function = "NDTR4";
-						groups = "NDTR4";
-					};
-
-					pinctrl_nri1_default: nri1_default {
-						function = "NRI1";
-						groups = "NRI1";
-					};
-
-					pinctrl_nri2_default: nri2_default {
-						function = "NRI2";
-						groups = "NRI2";
-					};
-
-					pinctrl_nri3_default: nri3_default {
-						function = "NRI3";
-						groups = "NRI3";
-					};
-
-					pinctrl_nri4_default: nri4_default {
-						function = "NRI4";
-						groups = "NRI4";
-					};
-
-					pinctrl_nrts1_default: nrts1_default {
-						function = "NRTS1";
-						groups = "NRTS1";
-					};
-
-					pinctrl_nrts2_default: nrts2_default {
-						function = "NRTS2";
-						groups = "NRTS2";
-					};
-
-					pinctrl_nrts3_default: nrts3_default {
-						function = "NRTS3";
-						groups = "NRTS3";
-					};
-
-					pinctrl_nrts4_default: nrts4_default {
-						function = "NRTS4";
-						groups = "NRTS4";
-					};
-
-					pinctrl_oscclk_default: oscclk_default {
-						function = "OSCCLK";
-						groups = "OSCCLK";
-					};
-
-					pinctrl_pewake_default: pewake_default {
-						function = "PEWAKE";
-						groups = "PEWAKE";
-					};
-
-					pinctrl_pnor_default: pnor_default {
-						function = "PNOR";
-						groups = "PNOR";
-					};
-
-					pinctrl_pwm0_default: pwm0_default {
-						function = "PWM0";
-						groups = "PWM0";
-					};
-
-					pinctrl_pwm1_default: pwm1_default {
-						function = "PWM1";
-						groups = "PWM1";
-					};
-
-					pinctrl_pwm2_default: pwm2_default {
-						function = "PWM2";
-						groups = "PWM2";
-					};
-
-					pinctrl_pwm3_default: pwm3_default {
-						function = "PWM3";
-						groups = "PWM3";
-					};
-
-					pinctrl_pwm4_default: pwm4_default {
-						function = "PWM4";
-						groups = "PWM4";
-					};
-
-					pinctrl_pwm5_default: pwm5_default {
-						function = "PWM5";
-						groups = "PWM5";
-					};
-
-					pinctrl_pwm6_default: pwm6_default {
-						function = "PWM6";
-						groups = "PWM6";
-					};
-
-					pinctrl_pwm7_default: pwm7_default {
-						function = "PWM7";
-						groups = "PWM7";
-					};
-
-					pinctrl_rgmii1_default: rgmii1_default {
-						function = "RGMII1";
-						groups = "RGMII1";
-					};
-
-					pinctrl_rgmii2_default: rgmii2_default {
-						function = "RGMII2";
-						groups = "RGMII2";
-					};
-
-					pinctrl_rmii1_default: rmii1_default {
-						function = "RMII1";
-						groups = "RMII1";
-					};
-
-					pinctrl_rmii2_default: rmii2_default {
-						function = "RMII2";
-						groups = "RMII2";
-					};
-
-					pinctrl_rxd1_default: rxd1_default {
-						function = "RXD1";
-						groups = "RXD1";
-					};
-
-					pinctrl_rxd2_default: rxd2_default {
-						function = "RXD2";
-						groups = "RXD2";
-					};
-
-					pinctrl_rxd3_default: rxd3_default {
-						function = "RXD3";
-						groups = "RXD3";
-					};
-
-					pinctrl_rxd4_default: rxd4_default {
-						function = "RXD4";
-						groups = "RXD4";
-					};
-
-					pinctrl_salt1_default: salt1_default {
-						function = "SALT1";
-						groups = "SALT1";
-					};
-
-					pinctrl_salt10_default: salt10_default {
-						function = "SALT10";
-						groups = "SALT10";
-					};
-
-					pinctrl_salt11_default: salt11_default {
-						function = "SALT11";
-						groups = "SALT11";
-					};
-
-					pinctrl_salt12_default: salt12_default {
-						function = "SALT12";
-						groups = "SALT12";
-					};
-
-					pinctrl_salt13_default: salt13_default {
-						function = "SALT13";
-						groups = "SALT13";
-					};
-
-					pinctrl_salt14_default: salt14_default {
-						function = "SALT14";
-						groups = "SALT14";
-					};
-
-					pinctrl_salt2_default: salt2_default {
-						function = "SALT2";
-						groups = "SALT2";
-					};
-
-					pinctrl_salt3_default: salt3_default {
-						function = "SALT3";
-						groups = "SALT3";
-					};
-
-					pinctrl_salt4_default: salt4_default {
-						function = "SALT4";
-						groups = "SALT4";
-					};
-
-					pinctrl_salt5_default: salt5_default {
-						function = "SALT5";
-						groups = "SALT5";
-					};
-
-					pinctrl_salt6_default: salt6_default {
-						function = "SALT6";
-						groups = "SALT6";
-					};
-
-					pinctrl_salt7_default: salt7_default {
-						function = "SALT7";
-						groups = "SALT7";
-					};
-
-					pinctrl_salt8_default: salt8_default {
-						function = "SALT8";
-						groups = "SALT8";
-					};
-
-					pinctrl_salt9_default: salt9_default {
-						function = "SALT9";
-						groups = "SALT9";
-					};
-
-					pinctrl_scl1_default: scl1_default {
-						function = "SCL1";
-						groups = "SCL1";
-					};
-
-					pinctrl_scl2_default: scl2_default {
-						function = "SCL2";
-						groups = "SCL2";
-					};
-
-					pinctrl_sd1_default: sd1_default {
-						function = "SD1";
-						groups = "SD1";
-					};
-
-					pinctrl_sd2_default: sd2_default {
-						function = "SD2";
-						groups = "SD2";
-					};
-
-					pinctrl_sda1_default: sda1_default {
-						function = "SDA1";
-						groups = "SDA1";
-					};
-
-					pinctrl_sda2_default: sda2_default {
-						function = "SDA2";
-						groups = "SDA2";
-					};
-
-					pinctrl_sgps1_default: sgps1_default {
-						function = "SGPS1";
-						groups = "SGPS1";
-					};
-
-					pinctrl_sgps2_default: sgps2_default {
-						function = "SGPS2";
-						groups = "SGPS2";
-					};
-
-					pinctrl_sioonctrl_default: sioonctrl_default {
-						function = "SIOONCTRL";
-						groups = "SIOONCTRL";
-					};
-
-					pinctrl_siopbi_default: siopbi_default {
-						function = "SIOPBI";
-						groups = "SIOPBI";
-					};
-
-					pinctrl_siopbo_default: siopbo_default {
-						function = "SIOPBO";
-						groups = "SIOPBO";
-					};
-
-					pinctrl_siopwreq_default: siopwreq_default {
-						function = "SIOPWREQ";
-						groups = "SIOPWREQ";
-					};
-
-					pinctrl_siopwrgd_default: siopwrgd_default {
-						function = "SIOPWRGD";
-						groups = "SIOPWRGD";
-					};
-
-					pinctrl_sios3_default: sios3_default {
-						function = "SIOS3";
-						groups = "SIOS3";
-					};
-
-					pinctrl_sios5_default: sios5_default {
-						function = "SIOS5";
-						groups = "SIOS5";
-					};
-
-					pinctrl_siosci_default: siosci_default {
-						function = "SIOSCI";
-						groups = "SIOSCI";
-					};
-
-					pinctrl_spi1_default: spi1_default {
-						function = "SPI1";
-						groups = "SPI1";
-					};
-
-					pinctrl_spi1cs1_default: spi1cs1_default {
-						function = "SPI1CS1";
-						groups = "SPI1CS1";
-					};
-
-					pinctrl_spi1debug_default: spi1debug_default {
-						function = "SPI1DEBUG";
-						groups = "SPI1DEBUG";
-					};
-
-					pinctrl_spi1passthru_default: spi1passthru_default {
-						function = "SPI1PASSTHRU";
-						groups = "SPI1PASSTHRU";
-					};
-
-					pinctrl_spi2ck_default: spi2ck_default {
-						function = "SPI2CK";
-						groups = "SPI2CK";
-					};
-
-					pinctrl_spi2cs0_default: spi2cs0_default {
-						function = "SPI2CS0";
-						groups = "SPI2CS0";
-					};
-
-					pinctrl_spi2cs1_default: spi2cs1_default {
-						function = "SPI2CS1";
-						groups = "SPI2CS1";
-					};
-
-					pinctrl_spi2miso_default: spi2miso_default {
-						function = "SPI2MISO";
-						groups = "SPI2MISO";
-					};
-
-					pinctrl_spi2mosi_default: spi2mosi_default {
-						function = "SPI2MOSI";
-						groups = "SPI2MOSI";
-					};
-
-					pinctrl_timer3_default: timer3_default {
-						function = "TIMER3";
-						groups = "TIMER3";
-					};
-
-					pinctrl_timer4_default: timer4_default {
-						function = "TIMER4";
-						groups = "TIMER4";
-					};
-
-					pinctrl_timer5_default: timer5_default {
-						function = "TIMER5";
-						groups = "TIMER5";
-					};
-
-					pinctrl_timer6_default: timer6_default {
-						function = "TIMER6";
-						groups = "TIMER6";
-					};
-
-					pinctrl_timer7_default: timer7_default {
-						function = "TIMER7";
-						groups = "TIMER7";
-					};
-
-					pinctrl_timer8_default: timer8_default {
-						function = "TIMER8";
-						groups = "TIMER8";
-					};
-
-					pinctrl_txd1_default: txd1_default {
-						function = "TXD1";
-						groups = "TXD1";
-					};
-
-					pinctrl_txd2_default: txd2_default {
-						function = "TXD2";
-						groups = "TXD2";
-					};
-
-					pinctrl_txd3_default: txd3_default {
-						function = "TXD3";
-						groups = "TXD3";
-					};
-
-					pinctrl_txd4_default: txd4_default {
-						function = "TXD4";
-						groups = "TXD4";
-					};
-
-					pinctrl_uart6_default: uart6_default {
-						function = "UART6";
-						groups = "UART6";
-					};
-
-					pinctrl_usbcki_default: usbcki_default {
-						function = "USBCKI";
-						groups = "USBCKI";
-					};
-
-					pinctrl_vgabiosrom_default: vgabiosrom_default {
-						function = "VGABIOSROM";
-						groups = "VGABIOSROM";
-					};
-
-					pinctrl_vgahs_default: vgahs_default {
-						function = "VGAHS";
-						groups = "VGAHS";
-					};
-
-					pinctrl_vgavs_default: vgavs_default {
-						function = "VGAVS";
-						groups = "VGAVS";
-					};
-
-					pinctrl_vpi24_default: vpi24_default {
-						function = "VPI24";
-						groups = "VPI24";
-					};
-
-					pinctrl_vpo_default: vpo_default {
-						function = "VPO";
-						groups = "VPO";
-					};
-
-					pinctrl_wdtrst1_default: wdtrst1_default {
-						function = "WDTRST1";
-						groups = "WDTRST1";
-					};
-
-					pinctrl_wdtrst2_default: wdtrst2_default {
-						function = "WDTRST2";
-						groups = "WDTRST2";
-					};
-
 				};
 			};
 
-			clk_hpll: clk_hpll@1e6e2024 {
-				#clock-cells = <0>;
-				compatible = "aspeed,g5-hpll-clock";
-				reg = <0x1e6e2024 0x4>;
-				clocks = <&clk_clkin>;
-			};
-
-			clk_ahb: clk_ahb@1e6e2070 {
-				#clock-cells = <0>;
-				compatible = "aspeed,g5-ahb-clock";
-				reg = <0x1e6e2070 0x4>;
-				clocks = <&clk_hpll>;
-			};
-
-			clk_apb: clk_apb@1e6e2008 {
-				#clock-cells = <0>;
-				compatible = "aspeed,g5-apb-clock";
-				reg = <0x1e6e2008 0x4>;
-				clocks = <&clk_hpll>;
-			};
-
-			clk_uart: clk_uart@1e6e2008 {
-				#clock-cells = <0>;
-				compatible = "aspeed,uart-clock";
-				reg = <0x1e6e202c 0x4>;
+			rng: hwrng@1e6e2078 {
+				compatible = "timeriomem_rng";
+				reg = <0x1e6e2078 0x4>;
+				period = <1>;
+				quality = <100>;
 			};
 
 			gfx: display@1e6e6000 {
@@ -913,6 +195,13 @@
 				reg-io-width = <4>;
 			};
 
+			adc: adc@1e6e9000 {
+				compatible = "aspeed,ast2500-adc";
+				reg = <0x1e6e9000 0xb0>;
+				#io-channel-cells = <1>;
+				status = "disabled";
+			};
+
 			sram@1e720000 {
 				compatible = "mmio-sram";
 				reg = <0x1e720000 0x9000>;	// 36K
@@ -929,41 +218,61 @@
 			};
 
 			timer: timer@1e782000 {
+				/* This timer is a Faraday FTTMR010 derivative */
 				compatible = "aspeed,ast2400-timer";
 				reg = <0x1e782000 0x90>;
-				// The moxart_timer driver registers only one
-				// interrupt and assumes it's for timer 1
-				//interrupts = <16 17 18 35 36 37 38 39>;
-				interrupts = <16>;
-				clocks = <&clk_apb>;
 			};
 
+			uart1: serial@1e783000 {
+				compatible = "ns16550a";
+				reg = <0x1e783000 0x20>;
+				reg-shift = <2>;
+				interrupts = <9>;
+				no-loopback-test;
+				status = "disabled";
+			};
 
-			wdt1: wdt@1e785000 {
+			uart5: serial@1e784000 {
+				compatible = "ns16550a";
+				reg = <0x1e784000 0x20>;
+				reg-shift = <2>;
+				interrupts = <10>;
+				no-loopback-test;
+				status = "disabled";
+			};
+
+			wdt1: watchdog@1e785000 {
 				compatible = "aspeed,wdt";
 				reg = <0x1e785000 0x1c>;
 				interrupts = <27>;
 			};
 
-			wdt2: wdt@1e785020 {
+			wdt2: watchdog@1e785020 {
 				compatible = "aspeed,wdt";
 				reg = <0x1e785020 0x1c>;
 				interrupts = <27>;
 				status = "disabled";
 			};
 
-			wdt3: wdt@1e785040 {
+			wdt3: watchdog@1e785040 {
 				compatible = "aspeed,wdt";
-				reg = <0x1e785074 0x1c>;
+				reg = <0x1e785040 0x1c>;
 				status = "disabled";
 			};
 
-			uart1: serial@1e783000 {
-				compatible = "ns16550a";
-				reg = <0x1e783000 0x1000>;
+			pwm_tacho: pwm-tacho-controller@1e786000 {
+				compatible = "aspeed,ast2500-pwm-tacho";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0x1e786000 0x1000>;
+				status = "disabled";
+			};
+
+			vuart: serial@1e787000 {
+				compatible = "aspeed,ast2500-vuart";
+				reg = <0x1e787000 0x40>;
 				reg-shift = <2>;
-				interrupts = <9>;
-				clocks = <&clk_uart>;
+				interrupts = <8>;
 				no-loopback-test;
 				status = "disabled";
 			};
@@ -974,7 +283,7 @@
 
 				#address-cells = <1>;
 				#size-cells = <1>;
-				ranges = <0 0x1e789000 0x1000>;
+				ranges = <0x0 0x1e789000 0x1000>;
 
 				lpc_bmc: lpc-bmc@0 {
 					compatible = "aspeed,ast2500-lpc-bmc";
@@ -984,70 +293,1118 @@
 				lpc_host: lpc-host@80 {
 					compatible = "aspeed,ast2500-lpc-host", "simple-mfd", "syscon";
 					reg = <0x80 0x1e0>;
+					reg-io-width = <4>;
 
 					#address-cells = <1>;
 					#size-cells = <1>;
-					ranges = <0 0x80 0x1e0>;
+					ranges = <0x0 0x80 0x1e0>;
 
-					reg-io-width = <4>;
+					lpc_ctrl: lpc-ctrl@0 {
+						compatible = "aspeed,ast2500-lpc-ctrl";
+						reg = <0x0 0x80>;
+						status = "disabled";
+					};
+
+					lpc_snoop: lpc-snoop@0 {
+						compatible = "aspeed,ast2500-lpc-snoop";
+						reg = <0x0 0x80>;
+						interrupts = <8>;
+						status = "disabled";
+					};
 
 					lhc: lhc@20 {
 						compatible = "aspeed,ast2500-lhc";
 						reg = <0x20 0x24 0x48 0x8>;
 					};
+
+					lpc_reset: reset-controller@18 {
+						compatible = "aspeed,ast2500-lpc-reset";
+						reg = <0x18 0x4>;
+						#reset-cells = <1>;
+					};
+
+					ibt: ibt@c0 {
+						compatible = "aspeed,ast2500-ibt-bmc";
+						reg = <0xc0 0x18>;
+						interrupts = <8>;
+						status = "disabled";
+					};
 				};
 			};
 
 			uart2: serial@1e78d000 {
 				compatible = "ns16550a";
-				reg = <0x1e78d000 0x1000>;
+				reg = <0x1e78d000 0x20>;
 				reg-shift = <2>;
 				interrupts = <32>;
-				clocks = <&clk_uart>;
 				no-loopback-test;
 				status = "disabled";
 			};
 
 			uart3: serial@1e78e000 {
 				compatible = "ns16550a";
-				reg = <0x1e78e000 0x1000>;
+				reg = <0x1e78e000 0x20>;
 				reg-shift = <2>;
 				interrupts = <33>;
-				clocks = <&clk_uart>;
 				no-loopback-test;
 				status = "disabled";
 			};
 
 			uart4: serial@1e78f000 {
 				compatible = "ns16550a";
-				reg = <0x1e78f000 0x1000>;
+				reg = <0x1e78f000 0x20>;
 				reg-shift = <2>;
 				interrupts = <34>;
-				clocks = <&clk_uart>;
 				no-loopback-test;
 				status = "disabled";
 			};
 
-			uart5: serial@1e784000 {
-				compatible = "ns16550a";
-				reg = <0x1e784000 0x1000>;
-				reg-shift = <2>;
-				interrupts = <10>;
-				clocks = <&clk_uart>;
-				current-speed = <38400>;
-				no-loopback-test;
-				status = "disabled";
-			};
-
-			uart6: serial@1e787000 {
-				compatible = "ns16550a";
-				reg = <0x1e787000 0x1000>;
-				reg-shift = <2>;
-				interrupts = <10>;
-				clocks = <&clk_uart>;
-				no-loopback-test;
-				status = "disabled";
+			i2c: i2c@1e78a000 {
+				compatible = "simple-bus";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				ranges = <0 0x1e78a000 0x1000>;
 			};
 		};
 	};
 };
+
+&i2c {
+	i2c_ic: interrupt-controller@0 {
+		#interrupt-cells = <1>;
+		compatible = "aspeed,ast2500-i2c-ic";
+		reg = <0x0 0x40>;
+		interrupts = <12>;
+		interrupt-controller;
+	};
+
+	i2c0: i2c-bus@40 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		#interrupt-cells = <1>;
+
+		reg = <0x40 0x40>;
+		compatible = "aspeed,ast2500-i2c-bus";
+		bus-frequency = <100000>;
+		interrupts = <0>;
+		interrupt-parent = <&i2c_ic>;
+		status = "disabled";
+		/* Does not need pinctrl properties */
+	};
+
+	i2c1: i2c-bus@80 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		#interrupt-cells = <1>;
+
+		reg = <0x80 0x40>;
+		compatible = "aspeed,ast2500-i2c-bus";
+		bus-frequency = <100000>;
+		interrupts = <1>;
+		interrupt-parent = <&i2c_ic>;
+		status = "disabled";
+		/* Does not need pinctrl properties */
+	};
+
+	i2c2: i2c-bus@c0 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		#interrupt-cells = <1>;
+
+		reg = <0xc0 0x40>;
+		compatible = "aspeed,ast2500-i2c-bus";
+		bus-frequency = <100000>;
+		interrupts = <2>;
+		interrupt-parent = <&i2c_ic>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_i2c3_default>;
+		status = "disabled";
+	};
+
+	i2c3: i2c-bus@100 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		#interrupt-cells = <1>;
+
+		reg = <0x100 0x40>;
+		compatible = "aspeed,ast2500-i2c-bus";
+		bus-frequency = <100000>;
+		interrupts = <3>;
+		interrupt-parent = <&i2c_ic>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_i2c4_default>;
+		status = "disabled";
+	};
+
+	i2c4: i2c-bus@140 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		#interrupt-cells = <1>;
+
+		reg = <0x140 0x40>;
+		compatible = "aspeed,ast2500-i2c-bus";
+		bus-frequency = <100000>;
+		interrupts = <4>;
+		interrupt-parent = <&i2c_ic>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_i2c5_default>;
+		status = "disabled";
+	};
+
+	i2c5: i2c-bus@180 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		#interrupt-cells = <1>;
+
+		reg = <0x180 0x40>;
+		compatible = "aspeed,ast2500-i2c-bus";
+		bus-frequency = <100000>;
+		interrupts = <5>;
+		interrupt-parent = <&i2c_ic>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_i2c6_default>;
+		status = "disabled";
+	};
+
+	i2c6: i2c-bus@1c0 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		#interrupt-cells = <1>;
+
+		reg = <0x1c0 0x40>;
+		compatible = "aspeed,ast2500-i2c-bus";
+		bus-frequency = <100000>;
+		interrupts = <6>;
+		interrupt-parent = <&i2c_ic>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_i2c7_default>;
+		status = "disabled";
+	};
+
+	i2c7: i2c-bus@300 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		#interrupt-cells = <1>;
+
+		reg = <0x300 0x40>;
+		compatible = "aspeed,ast2500-i2c-bus";
+		bus-frequency = <100000>;
+		interrupts = <7>;
+		interrupt-parent = <&i2c_ic>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_i2c8_default>;
+		status = "disabled";
+	};
+
+	i2c8: i2c-bus@340 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		#interrupt-cells = <1>;
+
+		reg = <0x340 0x40>;
+		compatible = "aspeed,ast2500-i2c-bus";
+		bus-frequency = <100000>;
+		interrupts = <8>;
+		interrupt-parent = <&i2c_ic>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_i2c9_default>;
+		status = "disabled";
+	};
+
+	i2c9: i2c-bus@380 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		#interrupt-cells = <1>;
+
+		reg = <0x380 0x40>;
+		compatible = "aspeed,ast2500-i2c-bus";
+		bus-frequency = <100000>;
+		interrupts = <9>;
+		interrupt-parent = <&i2c_ic>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_i2c10_default>;
+		status = "disabled";
+	};
+
+	i2c10: i2c-bus@3c0 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		#interrupt-cells = <1>;
+
+		reg = <0x3c0 0x40>;
+		compatible = "aspeed,ast2500-i2c-bus";
+		bus-frequency = <100000>;
+		interrupts = <10>;
+		interrupt-parent = <&i2c_ic>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_i2c11_default>;
+		status = "disabled";
+	};
+
+	i2c11: i2c-bus@400 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		#interrupt-cells = <1>;
+
+		reg = <0x400 0x40>;
+		compatible = "aspeed,ast2500-i2c-bus";
+		bus-frequency = <100000>;
+		interrupts = <11>;
+		interrupt-parent = <&i2c_ic>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_i2c12_default>;
+		status = "disabled";
+	};
+
+	i2c12: i2c-bus@440 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		#interrupt-cells = <1>;
+
+		reg = <0x440 0x40>;
+		compatible = "aspeed,ast2500-i2c-bus";
+		bus-frequency = <100000>;
+		interrupts = <12>;
+		interrupt-parent = <&i2c_ic>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_i2c13_default>;
+		status = "disabled";
+	};
+
+	i2c13: i2c-bus@480 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		#interrupt-cells = <1>;
+
+		reg = <0x480 0x40>;
+		compatible = "aspeed,ast2500-i2c-bus";
+		bus-frequency = <100000>;
+		interrupts = <13>;
+		interrupt-parent = <&i2c_ic>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_i2c14_default>;
+		status = "disabled";
+	};
+};
+
+&pinctrl {
+	pinctrl_acpi_default: acpi_default {
+		function = "ACPI";
+		groups = "ACPI";
+	};
+
+	pinctrl_adc0_default: adc0_default {
+		function = "ADC0";
+		groups = "ADC0";
+	};
+
+	pinctrl_adc1_default: adc1_default {
+		function = "ADC1";
+		groups = "ADC1";
+	};
+
+	pinctrl_adc10_default: adc10_default {
+		function = "ADC10";
+		groups = "ADC10";
+	};
+
+	pinctrl_adc11_default: adc11_default {
+		function = "ADC11";
+		groups = "ADC11";
+	};
+
+	pinctrl_adc12_default: adc12_default {
+		function = "ADC12";
+		groups = "ADC12";
+	};
+
+	pinctrl_adc13_default: adc13_default {
+		function = "ADC13";
+		groups = "ADC13";
+	};
+
+	pinctrl_adc14_default: adc14_default {
+		function = "ADC14";
+		groups = "ADC14";
+	};
+
+	pinctrl_adc15_default: adc15_default {
+		function = "ADC15";
+		groups = "ADC15";
+	};
+
+	pinctrl_adc2_default: adc2_default {
+		function = "ADC2";
+		groups = "ADC2";
+	};
+
+	pinctrl_adc3_default: adc3_default {
+		function = "ADC3";
+		groups = "ADC3";
+	};
+
+	pinctrl_adc4_default: adc4_default {
+		function = "ADC4";
+		groups = "ADC4";
+	};
+
+	pinctrl_adc5_default: adc5_default {
+		function = "ADC5";
+		groups = "ADC5";
+	};
+
+	pinctrl_adc6_default: adc6_default {
+		function = "ADC6";
+		groups = "ADC6";
+	};
+
+	pinctrl_adc7_default: adc7_default {
+		function = "ADC7";
+		groups = "ADC7";
+	};
+
+	pinctrl_adc8_default: adc8_default {
+		function = "ADC8";
+		groups = "ADC8";
+	};
+
+	pinctrl_adc9_default: adc9_default {
+		function = "ADC9";
+		groups = "ADC9";
+	};
+
+	pinctrl_bmcint_default: bmcint_default {
+		function = "BMCINT";
+		groups = "BMCINT";
+	};
+
+	pinctrl_ddcclk_default: ddcclk_default {
+		function = "DDCCLK";
+		groups = "DDCCLK";
+	};
+
+	pinctrl_ddcdat_default: ddcdat_default {
+		function = "DDCDAT";
+		groups = "DDCDAT";
+	};
+
+	pinctrl_espi_default: espi_default {
+		function = "ESPI";
+		groups = "ESPI";
+	};
+
+	pinctrl_fwspics1_default: fwspics1_default {
+		function = "FWSPICS1";
+		groups = "FWSPICS1";
+	};
+
+	pinctrl_fwspics2_default: fwspics2_default {
+		function = "FWSPICS2";
+		groups = "FWSPICS2";
+	};
+
+	pinctrl_gpid0_default: gpid0_default {
+		function = "GPID0";
+		groups = "GPID0";
+	};
+
+	pinctrl_gpid2_default: gpid2_default {
+		function = "GPID2";
+		groups = "GPID2";
+	};
+
+	pinctrl_gpid4_default: gpid4_default {
+		function = "GPID4";
+		groups = "GPID4";
+	};
+
+	pinctrl_gpid6_default: gpid6_default {
+		function = "GPID6";
+		groups = "GPID6";
+	};
+
+	pinctrl_gpie0_default: gpie0_default {
+		function = "GPIE0";
+		groups = "GPIE0";
+	};
+
+	pinctrl_gpie2_default: gpie2_default {
+		function = "GPIE2";
+		groups = "GPIE2";
+	};
+
+	pinctrl_gpie4_default: gpie4_default {
+		function = "GPIE4";
+		groups = "GPIE4";
+	};
+
+	pinctrl_gpie6_default: gpie6_default {
+		function = "GPIE6";
+		groups = "GPIE6";
+	};
+
+	pinctrl_i2c10_default: i2c10_default {
+		function = "I2C10";
+		groups = "I2C10";
+	};
+
+	pinctrl_i2c11_default: i2c11_default {
+		function = "I2C11";
+		groups = "I2C11";
+	};
+
+	pinctrl_i2c12_default: i2c12_default {
+		function = "I2C12";
+		groups = "I2C12";
+	};
+
+	pinctrl_i2c13_default: i2c13_default {
+		function = "I2C13";
+		groups = "I2C13";
+	};
+
+	pinctrl_i2c14_default: i2c14_default {
+		function = "I2C14";
+		groups = "I2C14";
+	};
+
+	pinctrl_i2c3_default: i2c3_default {
+		function = "I2C3";
+		groups = "I2C3";
+	};
+
+	pinctrl_i2c4_default: i2c4_default {
+		function = "I2C4";
+		groups = "I2C4";
+	};
+
+	pinctrl_i2c5_default: i2c5_default {
+		function = "I2C5";
+		groups = "I2C5";
+	};
+
+	pinctrl_i2c6_default: i2c6_default {
+		function = "I2C6";
+		groups = "I2C6";
+	};
+
+	pinctrl_i2c7_default: i2c7_default {
+		function = "I2C7";
+		groups = "I2C7";
+	};
+
+	pinctrl_i2c8_default: i2c8_default {
+		function = "I2C8";
+		groups = "I2C8";
+	};
+
+	pinctrl_i2c9_default: i2c9_default {
+		function = "I2C9";
+		groups = "I2C9";
+	};
+
+	pinctrl_lad0_default: lad0_default {
+		function = "LAD0";
+		groups = "LAD0";
+	};
+
+	pinctrl_lad1_default: lad1_default {
+		function = "LAD1";
+		groups = "LAD1";
+	};
+
+	pinctrl_lad2_default: lad2_default {
+		function = "LAD2";
+		groups = "LAD2";
+	};
+
+	pinctrl_lad3_default: lad3_default {
+		function = "LAD3";
+		groups = "LAD3";
+	};
+
+	pinctrl_lclk_default: lclk_default {
+		function = "LCLK";
+		groups = "LCLK";
+	};
+
+	pinctrl_lframe_default: lframe_default {
+		function = "LFRAME";
+		groups = "LFRAME";
+	};
+
+	pinctrl_lpchc_default: lpchc_default {
+		function = "LPCHC";
+		groups = "LPCHC";
+	};
+
+	pinctrl_lpcpd_default: lpcpd_default {
+		function = "LPCPD";
+		groups = "LPCPD";
+	};
+
+	pinctrl_lpcplus_default: lpcplus_default {
+		function = "LPCPLUS";
+		groups = "LPCPLUS";
+	};
+
+	pinctrl_lpcpme_default: lpcpme_default {
+		function = "LPCPME";
+		groups = "LPCPME";
+	};
+
+	pinctrl_lpcrst_default: lpcrst_default {
+		function = "LPCRST";
+		groups = "LPCRST";
+	};
+
+	pinctrl_lpcsmi_default: lpcsmi_default {
+		function = "LPCSMI";
+		groups = "LPCSMI";
+	};
+
+	pinctrl_lsirq_default: lsirq_default {
+		function = "LSIRQ";
+		groups = "LSIRQ";
+	};
+
+	pinctrl_mac1link_default: mac1link_default {
+		function = "MAC1LINK";
+		groups = "MAC1LINK";
+	};
+
+	pinctrl_mac2link_default: mac2link_default {
+		function = "MAC2LINK";
+		groups = "MAC2LINK";
+	};
+
+	pinctrl_mdio1_default: mdio1_default {
+		function = "MDIO1";
+		groups = "MDIO1";
+	};
+
+	pinctrl_mdio2_default: mdio2_default {
+		function = "MDIO2";
+		groups = "MDIO2";
+	};
+
+	pinctrl_ncts1_default: ncts1_default {
+		function = "NCTS1";
+		groups = "NCTS1";
+	};
+
+	pinctrl_ncts2_default: ncts2_default {
+		function = "NCTS2";
+		groups = "NCTS2";
+	};
+
+	pinctrl_ncts3_default: ncts3_default {
+		function = "NCTS3";
+		groups = "NCTS3";
+	};
+
+	pinctrl_ncts4_default: ncts4_default {
+		function = "NCTS4";
+		groups = "NCTS4";
+	};
+
+	pinctrl_ndcd1_default: ndcd1_default {
+		function = "NDCD1";
+		groups = "NDCD1";
+	};
+
+	pinctrl_ndcd2_default: ndcd2_default {
+		function = "NDCD2";
+		groups = "NDCD2";
+	};
+
+	pinctrl_ndcd3_default: ndcd3_default {
+		function = "NDCD3";
+		groups = "NDCD3";
+	};
+
+	pinctrl_ndcd4_default: ndcd4_default {
+		function = "NDCD4";
+		groups = "NDCD4";
+	};
+
+	pinctrl_ndsr1_default: ndsr1_default {
+		function = "NDSR1";
+		groups = "NDSR1";
+	};
+
+	pinctrl_ndsr2_default: ndsr2_default {
+		function = "NDSR2";
+		groups = "NDSR2";
+	};
+
+	pinctrl_ndsr3_default: ndsr3_default {
+		function = "NDSR3";
+		groups = "NDSR3";
+	};
+
+	pinctrl_ndsr4_default: ndsr4_default {
+		function = "NDSR4";
+		groups = "NDSR4";
+	};
+
+	pinctrl_ndtr1_default: ndtr1_default {
+		function = "NDTR1";
+		groups = "NDTR1";
+	};
+
+	pinctrl_ndtr2_default: ndtr2_default {
+		function = "NDTR2";
+		groups = "NDTR2";
+	};
+
+	pinctrl_ndtr3_default: ndtr3_default {
+		function = "NDTR3";
+		groups = "NDTR3";
+	};
+
+	pinctrl_ndtr4_default: ndtr4_default {
+		function = "NDTR4";
+		groups = "NDTR4";
+	};
+
+	pinctrl_nri1_default: nri1_default {
+		function = "NRI1";
+		groups = "NRI1";
+	};
+
+	pinctrl_nri2_default: nri2_default {
+		function = "NRI2";
+		groups = "NRI2";
+	};
+
+	pinctrl_nri3_default: nri3_default {
+		function = "NRI3";
+		groups = "NRI3";
+	};
+
+	pinctrl_nri4_default: nri4_default {
+		function = "NRI4";
+		groups = "NRI4";
+	};
+
+	pinctrl_nrts1_default: nrts1_default {
+		function = "NRTS1";
+		groups = "NRTS1";
+	};
+
+	pinctrl_nrts2_default: nrts2_default {
+		function = "NRTS2";
+		groups = "NRTS2";
+	};
+
+	pinctrl_nrts3_default: nrts3_default {
+		function = "NRTS3";
+		groups = "NRTS3";
+	};
+
+	pinctrl_nrts4_default: nrts4_default {
+		function = "NRTS4";
+		groups = "NRTS4";
+	};
+
+	pinctrl_oscclk_default: oscclk_default {
+		function = "OSCCLK";
+		groups = "OSCCLK";
+	};
+
+	pinctrl_pewake_default: pewake_default {
+		function = "PEWAKE";
+		groups = "PEWAKE";
+	};
+
+	pinctrl_pnor_default: pnor_default {
+		function = "PNOR";
+		groups = "PNOR";
+	};
+
+	pinctrl_pwm0_default: pwm0_default {
+		function = "PWM0";
+		groups = "PWM0";
+	};
+
+	pinctrl_pwm1_default: pwm1_default {
+		function = "PWM1";
+		groups = "PWM1";
+	};
+
+	pinctrl_pwm2_default: pwm2_default {
+		function = "PWM2";
+		groups = "PWM2";
+	};
+
+	pinctrl_pwm3_default: pwm3_default {
+		function = "PWM3";
+		groups = "PWM3";
+	};
+
+	pinctrl_pwm4_default: pwm4_default {
+		function = "PWM4";
+		groups = "PWM4";
+	};
+
+	pinctrl_pwm5_default: pwm5_default {
+		function = "PWM5";
+		groups = "PWM5";
+	};
+
+	pinctrl_pwm6_default: pwm6_default {
+		function = "PWM6";
+		groups = "PWM6";
+	};
+
+	pinctrl_pwm7_default: pwm7_default {
+		function = "PWM7";
+		groups = "PWM7";
+	};
+
+	pinctrl_rgmii1_default: rgmii1_default {
+		function = "RGMII1";
+		groups = "RGMII1";
+	};
+
+	pinctrl_rgmii2_default: rgmii2_default {
+		function = "RGMII2";
+		groups = "RGMII2";
+	};
+
+	pinctrl_rmii1_default: rmii1_default {
+		function = "RMII1";
+		groups = "RMII1";
+	};
+
+	pinctrl_rmii2_default: rmii2_default {
+		function = "RMII2";
+		groups = "RMII2";
+	};
+
+	pinctrl_rxd1_default: rxd1_default {
+		function = "RXD1";
+		groups = "RXD1";
+	};
+
+	pinctrl_rxd2_default: rxd2_default {
+		function = "RXD2";
+		groups = "RXD2";
+	};
+
+	pinctrl_rxd3_default: rxd3_default {
+		function = "RXD3";
+		groups = "RXD3";
+	};
+
+	pinctrl_rxd4_default: rxd4_default {
+		function = "RXD4";
+		groups = "RXD4";
+	};
+
+	pinctrl_salt1_default: salt1_default {
+		function = "SALT1";
+		groups = "SALT1";
+	};
+
+	pinctrl_salt10_default: salt10_default {
+		function = "SALT10";
+		groups = "SALT10";
+	};
+
+	pinctrl_salt11_default: salt11_default {
+		function = "SALT11";
+		groups = "SALT11";
+	};
+
+	pinctrl_salt12_default: salt12_default {
+		function = "SALT12";
+		groups = "SALT12";
+	};
+
+	pinctrl_salt13_default: salt13_default {
+		function = "SALT13";
+		groups = "SALT13";
+	};
+
+	pinctrl_salt14_default: salt14_default {
+		function = "SALT14";
+		groups = "SALT14";
+	};
+
+	pinctrl_salt2_default: salt2_default {
+		function = "SALT2";
+		groups = "SALT2";
+	};
+
+	pinctrl_salt3_default: salt3_default {
+		function = "SALT3";
+		groups = "SALT3";
+	};
+
+	pinctrl_salt4_default: salt4_default {
+		function = "SALT4";
+		groups = "SALT4";
+	};
+
+	pinctrl_salt5_default: salt5_default {
+		function = "SALT5";
+		groups = "SALT5";
+	};
+
+	pinctrl_salt6_default: salt6_default {
+		function = "SALT6";
+		groups = "SALT6";
+	};
+
+	pinctrl_salt7_default: salt7_default {
+		function = "SALT7";
+		groups = "SALT7";
+	};
+
+	pinctrl_salt8_default: salt8_default {
+		function = "SALT8";
+		groups = "SALT8";
+	};
+
+	pinctrl_salt9_default: salt9_default {
+		function = "SALT9";
+		groups = "SALT9";
+	};
+
+	pinctrl_scl1_default: scl1_default {
+		function = "SCL1";
+		groups = "SCL1";
+	};
+
+	pinctrl_scl2_default: scl2_default {
+		function = "SCL2";
+		groups = "SCL2";
+	};
+
+	pinctrl_sd1_default: sd1_default {
+		function = "SD1";
+		groups = "SD1";
+	};
+
+	pinctrl_sd2_default: sd2_default {
+		function = "SD2";
+		groups = "SD2";
+	};
+
+	pinctrl_sda1_default: sda1_default {
+		function = "SDA1";
+		groups = "SDA1";
+	};
+
+	pinctrl_sda2_default: sda2_default {
+		function = "SDA2";
+		groups = "SDA2";
+	};
+
+	pinctrl_sgps1_default: sgps1_default {
+		function = "SGPS1";
+		groups = "SGPS1";
+	};
+
+	pinctrl_sgps2_default: sgps2_default {
+		function = "SGPS2";
+		groups = "SGPS2";
+	};
+
+	pinctrl_sioonctrl_default: sioonctrl_default {
+		function = "SIOONCTRL";
+		groups = "SIOONCTRL";
+	};
+
+	pinctrl_siopbi_default: siopbi_default {
+		function = "SIOPBI";
+		groups = "SIOPBI";
+	};
+
+	pinctrl_siopbo_default: siopbo_default {
+		function = "SIOPBO";
+		groups = "SIOPBO";
+	};
+
+	pinctrl_siopwreq_default: siopwreq_default {
+		function = "SIOPWREQ";
+		groups = "SIOPWREQ";
+	};
+
+	pinctrl_siopwrgd_default: siopwrgd_default {
+		function = "SIOPWRGD";
+		groups = "SIOPWRGD";
+	};
+
+	pinctrl_sios3_default: sios3_default {
+		function = "SIOS3";
+		groups = "SIOS3";
+	};
+
+	pinctrl_sios5_default: sios5_default {
+		function = "SIOS5";
+		groups = "SIOS5";
+	};
+
+	pinctrl_siosci_default: siosci_default {
+		function = "SIOSCI";
+		groups = "SIOSCI";
+	};
+
+	pinctrl_spi1_default: spi1_default {
+		function = "SPI1";
+		groups = "SPI1";
+	};
+
+	pinctrl_spi1cs1_default: spi1cs1_default {
+		function = "SPI1CS1";
+		groups = "SPI1CS1";
+	};
+
+	pinctrl_spi1debug_default: spi1debug_default {
+		function = "SPI1DEBUG";
+		groups = "SPI1DEBUG";
+	};
+
+	pinctrl_spi1passthru_default: spi1passthru_default {
+		function = "SPI1PASSTHRU";
+		groups = "SPI1PASSTHRU";
+	};
+
+	pinctrl_spi2ck_default: spi2ck_default {
+		function = "SPI2CK";
+		groups = "SPI2CK";
+	};
+
+	pinctrl_spi2cs0_default: spi2cs0_default {
+		function = "SPI2CS0";
+		groups = "SPI2CS0";
+	};
+
+	pinctrl_spi2cs1_default: spi2cs1_default {
+		function = "SPI2CS1";
+		groups = "SPI2CS1";
+	};
+
+	pinctrl_spi2miso_default: spi2miso_default {
+		function = "SPI2MISO";
+		groups = "SPI2MISO";
+	};
+
+	pinctrl_spi2mosi_default: spi2mosi_default {
+		function = "SPI2MOSI";
+		groups = "SPI2MOSI";
+	};
+
+	pinctrl_timer3_default: timer3_default {
+		function = "TIMER3";
+		groups = "TIMER3";
+	};
+
+	pinctrl_timer4_default: timer4_default {
+		function = "TIMER4";
+		groups = "TIMER4";
+	};
+
+	pinctrl_timer5_default: timer5_default {
+		function = "TIMER5";
+		groups = "TIMER5";
+	};
+
+	pinctrl_timer6_default: timer6_default {
+		function = "TIMER6";
+		groups = "TIMER6";
+	};
+
+	pinctrl_timer7_default: timer7_default {
+		function = "TIMER7";
+		groups = "TIMER7";
+	};
+
+	pinctrl_timer8_default: timer8_default {
+		function = "TIMER8";
+		groups = "TIMER8";
+	};
+
+	pinctrl_txd1_default: txd1_default {
+		function = "TXD1";
+		groups = "TXD1";
+	};
+
+	pinctrl_txd2_default: txd2_default {
+		function = "TXD2";
+		groups = "TXD2";
+	};
+
+	pinctrl_txd3_default: txd3_default {
+		function = "TXD3";
+		groups = "TXD3";
+	};
+
+	pinctrl_txd4_default: txd4_default {
+		function = "TXD4";
+		groups = "TXD4";
+	};
+
+	pinctrl_uart6_default: uart6_default {
+		function = "UART6";
+		groups = "UART6";
+	};
+
+	pinctrl_usbcki_default: usbcki_default {
+		function = "USBCKI";
+		groups = "USBCKI";
+	};
+
+	pinctrl_usb2ah_default: usb2ah_default {
+		function = "USB2AH";
+		groups = "USB2AH";
+	};
+
+	pinctrl_usb11bhid_default: usb11bhid_default {
+		function = "USB11BHID";
+		groups = "USB11BHID";
+	};
+
+	pinctrl_usb2bh_default: usb2bh_default {
+		function = "USB2BH";
+		groups = "USB2BH";
+	};
+
+	pinctrl_vgabiosrom_default: vgabiosrom_default {
+		function = "VGABIOSROM";
+		groups = "VGABIOSROM";
+	};
+
+	pinctrl_vgahs_default: vgahs_default {
+		function = "VGAHS";
+		groups = "VGAHS";
+	};
+
+	pinctrl_vgavs_default: vgavs_default {
+		function = "VGAVS";
+		groups = "VGAVS";
+	};
+
+	pinctrl_vpi24_default: vpi24_default {
+		function = "VPI24";
+		groups = "VPI24";
+	};
+
+	pinctrl_vpo_default: vpo_default {
+		function = "VPO";
+		groups = "VPO";
+	};
+
+	pinctrl_wdtrst1_default: wdtrst1_default {
+		function = "WDTRST1";
+		groups = "WDTRST1";
+	};
+
+	pinctrl_wdtrst2_default: wdtrst2_default {
+		function = "WDTRST2";
+		groups = "WDTRST2";
+	};
+};
diff --git a/arch/arm/include/asm/ti-common/keystone_net.h b/arch/arm/include/asm/ti-common/keystone_net.h
index f89e043..bba1048 100644
--- a/arch/arm/include/asm/ti-common/keystone_net.h
+++ b/arch/arm/include/asm/ti-common/keystone_net.h
@@ -57,19 +57,6 @@
 /* MDIO clock output frequency */
 #define EMAC_MDIO_CLOCK_FREQ		2500000	/* 2.5 MHz */
 
-/* MII Status Register */
-#define MII_STATUS_REG			1
-#define MII_STATUS_LINK_MASK		0x4
-
-#define MDIO_CONTROL_IDLE		0x80000000
-#define MDIO_CONTROL_ENABLE		0x40000000
-#define MDIO_CONTROL_FAULT_ENABLE	0x40000
-#define MDIO_CONTROL_FAULT		0x80000
-#define MDIO_USERACCESS0_GO		0x80000000
-#define MDIO_USERACCESS0_WRITE_READ	0x0
-#define MDIO_USERACCESS0_WRITE_WRITE	0x40000000
-#define MDIO_USERACCESS0_ACK		0x20000000
-
 #define EMAC_MACCONTROL_MIIEN_ENABLE		0x20
 #define EMAC_MACCONTROL_FULLDUPLEX_ENABLE	0x1
 #define EMAC_MACCONTROL_GIGABIT_ENABLE		BIT(7)
@@ -242,18 +229,4 @@
 	u32 userphysel1;
 };
 
-struct eth_priv_t {
-	char int_name[32];
-	int rx_flow;
-	int phy_addr;
-	int slave_port;
-	int sgmii_link_type;
-	phy_interface_t phy_if;
-	struct phy_device *phy_dev;
-};
-
-int keystone2_emac_initialize(struct eth_priv_t *eth_priv);
-void sgmii_serdes_setup_156p25mhz(void);
-void sgmii_serdes_shutdown(void);
-
 #endif  /* _KEYSTONE_NET_H_ */
diff --git a/arch/arm/mach-davinci/dp83848.c b/arch/arm/mach-davinci/dp83848.c
index 595e3ca..7115d7b 100644
--- a/arch/arm/mach-davinci/dp83848.c
+++ b/arch/arm/mach-davinci/dp83848.c
@@ -12,7 +12,7 @@
 #include <net.h>
 #include <dp83848.h>
 #include <asm/arch/emac_defs.h>
-#include "../../../drivers/net/davinci_emac.h"
+#include "../../../drivers/net/ti/davinci_emac.h"
 
 #ifdef CONFIG_DRIVER_TI_EMAC
 
diff --git a/arch/arm/mach-davinci/et1011c.c b/arch/arm/mach-davinci/et1011c.c
index 3d02274..bfb7ff2 100644
--- a/arch/arm/mach-davinci/et1011c.c
+++ b/arch/arm/mach-davinci/et1011c.c
@@ -9,7 +9,7 @@
 #include <net.h>
 #include <miiphy.h>
 #include <asm/arch/emac_defs.h>
-#include "../../../drivers/net/davinci_emac.h"
+#include "../../../drivers/net/ti/davinci_emac.h"
 
 #ifdef CONFIG_DRIVER_TI_EMAC
 
diff --git a/arch/arm/mach-davinci/ksz8873.c b/arch/arm/mach-davinci/ksz8873.c
index 899cff0..85b0c26 100644
--- a/arch/arm/mach-davinci/ksz8873.c
+++ b/arch/arm/mach-davinci/ksz8873.c
@@ -19,7 +19,7 @@
 #include <net.h>
 #include <asm/arch/emac_defs.h>
 #include <asm/io.h>
-#include "../../../drivers/net/davinci_emac.h"
+#include "../../../drivers/net/ti/davinci_emac.h"
 
 int ksz8873_is_phy_connected(int phy_addr)
 {
diff --git a/arch/arm/mach-davinci/lxt972.c b/arch/arm/mach-davinci/lxt972.c
index 170e4a5..b54f67d 100644
--- a/arch/arm/mach-davinci/lxt972.c
+++ b/arch/arm/mach-davinci/lxt972.c
@@ -13,7 +13,7 @@
 #include <miiphy.h>
 #include <lxt971a.h>
 #include <asm/arch/emac_defs.h>
-#include "../../../drivers/net/davinci_emac.h"
+#include "../../../drivers/net/ti/davinci_emac.h"
 
 #ifdef CONFIG_DRIVER_TI_EMAC
 
diff --git a/board/ti/ks2_evm/board.c b/board/ti/ks2_evm/board.c
index d81c8e6..72709c0 100644
--- a/board/ti/ks2_evm/board.c
+++ b/board/ti/ks2_evm/board.c
@@ -66,59 +66,6 @@
 	return 0;
 }
 
-#ifdef CONFIG_DRIVER_TI_KEYSTONE_NET
-#ifndef CONFIG_DM_ETH
-int get_eth_env_param(char *env_name)
-{
-	char *env;
-	int res = -1;
-
-	env = env_get(env_name);
-	if (env)
-		res = simple_strtol(env, NULL, 0);
-
-	return res;
-}
-
-int board_eth_init(bd_t *bis)
-{
-	int j;
-	int res;
-	int port_num;
-	char link_type_name[32];
-
-	if (cpu_is_k2g())
-		writel(KS2_ETHERNET_RGMII, KS2_ETHERNET_CFG);
-
-	/* By default, select PA PLL clock as PA clock source */
-#ifndef CONFIG_SOC_K2G
-	if (psc_enable_module(KS2_LPSC_PA))
-		return -1;
-#endif
-	if (psc_enable_module(KS2_LPSC_CPGMAC))
-		return -1;
-	if (psc_enable_module(KS2_LPSC_CRYPTO))
-		return -1;
-
-	if (cpu_is_k2e() || cpu_is_k2l())
-		pll_pa_clk_sel();
-
-	port_num = get_num_eth_ports();
-
-	for (j = 0; j < port_num; j++) {
-		sprintf(link_type_name, "sgmii%d_link_type", j);
-		res = get_eth_env_param(link_type_name);
-		if (res >= 0)
-			eth_priv_cfg[j].sgmii_link_type = res;
-
-		keystone2_emac_initialize(&eth_priv_cfg[j]);
-	}
-
-	return 0;
-}
-#endif
-#endif
-
 #ifdef CONFIG_SPL_BUILD
 void spl_board_init(void)
 {
diff --git a/board/ti/ks2_evm/board.h b/board/ti/ks2_evm/board.h
index 250b649..d0cfbf5 100644
--- a/board/ti/ks2_evm/board.h
+++ b/board/ti/ks2_evm/board.h
@@ -12,8 +12,6 @@
 #include <asm/ti-common/keystone_net.h>
 #include "../common/board_detect.h"
 
-extern struct eth_priv_t eth_priv_cfg[];
-
 #if defined(CONFIG_TI_I2C_BOARD_DETECT)
 static inline int board_is_k2g_gp(void)
 {
@@ -38,7 +36,6 @@
 }
 #endif
 
-int get_num_eth_ports(void);
 void spl_init_keystone_plls(void);
 
 #endif
diff --git a/board/ti/ks2_evm/board_k2e.c b/board/ti/ks2_evm/board_k2e.c
index f86a836..ecd4a42 100644
--- a/board/ti/ks2_evm/board_k2e.c
+++ b/board/ti/ks2_evm/board_k2e.c
@@ -89,80 +89,6 @@
 	return data;
 }
 
-#ifdef CONFIG_DRIVER_TI_KEYSTONE_NET
-struct eth_priv_t eth_priv_cfg[] = {
-	{
-		.int_name        = "K2E_EMAC0",
-		.rx_flow         = 0,
-		.phy_addr        = 0,
-		.slave_port      = 1,
-		.sgmii_link_type = SGMII_LINK_MAC_PHY,
-		.phy_if          = PHY_INTERFACE_MODE_SGMII,
-	},
-	{
-		.int_name        = "K2E_EMAC1",
-		.rx_flow         = 8,
-		.phy_addr        = 1,
-		.slave_port      = 2,
-		.sgmii_link_type = SGMII_LINK_MAC_PHY,
-		.phy_if          = PHY_INTERFACE_MODE_SGMII,
-	},
-	{
-		.int_name        = "K2E_EMAC2",
-		.rx_flow         = 16,
-		.phy_addr        = 2,
-		.slave_port      = 3,
-		.sgmii_link_type = SGMII_LINK_MAC_MAC_FORCED,
-		.phy_if          = PHY_INTERFACE_MODE_SGMII,
-	},
-	{
-		.int_name        = "K2E_EMAC3",
-		.rx_flow         = 24,
-		.phy_addr        = 3,
-		.slave_port      = 4,
-		.sgmii_link_type = SGMII_LINK_MAC_MAC_FORCED,
-		.phy_if          = PHY_INTERFACE_MODE_SGMII,
-	},
-	{
-		.int_name        = "K2E_EMAC4",
-		.rx_flow         = 32,
-		.phy_addr        = 4,
-		.slave_port      = 5,
-		.sgmii_link_type = SGMII_LINK_MAC_MAC_FORCED,
-		.phy_if          = PHY_INTERFACE_MODE_SGMII,
-	},
-	{
-		.int_name        = "K2E_EMAC5",
-		.rx_flow         = 40,
-		.phy_addr        = 5,
-		.slave_port      = 6,
-		.sgmii_link_type = SGMII_LINK_MAC_MAC_FORCED,
-		.phy_if          = PHY_INTERFACE_MODE_SGMII,
-	},
-	{
-		.int_name        = "K2E_EMAC6",
-		.rx_flow         = 48,
-		.phy_addr        = 6,
-		.slave_port      = 7,
-		.sgmii_link_type = SGMII_LINK_MAC_MAC_FORCED,
-		.phy_if          = PHY_INTERFACE_MODE_SGMII,
-	},
-	{
-		.int_name        = "K2E_EMAC7",
-		.rx_flow         = 56,
-		.phy_addr        = 7,
-		.slave_port      = 8,
-		.sgmii_link_type = SGMII_LINK_MAC_MAC_FORCED,
-		.phy_if          = PHY_INTERFACE_MODE_SGMII,
-	},
-};
-
-int get_num_eth_ports(void)
-{
-	return sizeof(eth_priv_cfg) / sizeof(struct eth_priv_t);
-}
-#endif
-
 #if defined(CONFIG_MULTI_DTB_FIT)
 int board_fit_config_name_match(const char *name)
 {
diff --git a/board/ti/ks2_evm/board_k2g.c b/board/ti/ks2_evm/board_k2g.c
index 9bc94fb..87dc4d0 100644
--- a/board/ti/ks2_evm/board_k2g.c
+++ b/board/ti/ks2_evm/board_k2g.c
@@ -354,24 +354,6 @@
 }
 #endif
 
-#ifdef CONFIG_DRIVER_TI_KEYSTONE_NET
-struct eth_priv_t eth_priv_cfg[] = {
-	{
-		.int_name	= "K2G_EMAC",
-		.rx_flow	= 0,
-		.phy_addr	= 0,
-		.slave_port	= 1,
-		.sgmii_link_type = SGMII_LINK_MAC_PHY,
-		.phy_if          = PHY_INTERFACE_MODE_RGMII,
-	},
-};
-
-int get_num_eth_ports(void)
-{
-	return sizeof(eth_priv_cfg) / sizeof(struct eth_priv_t);
-}
-#endif
-
 #ifdef CONFIG_TI_SECURE_DEVICE
 void board_pmmc_image_process(ulong pmmc_image, size_t pmmc_size)
 {
diff --git a/board/ti/ks2_evm/board_k2hk.c b/board/ti/ks2_evm/board_k2hk.c
index abc89d8..4c0acd6 100644
--- a/board/ti/ks2_evm/board_k2hk.c
+++ b/board/ti/ks2_evm/board_k2hk.c
@@ -96,48 +96,6 @@
 	return data;
 }
 
-#ifdef CONFIG_DRIVER_TI_KEYSTONE_NET
-struct eth_priv_t eth_priv_cfg[] = {
-	{
-		.int_name	= "K2HK_EMAC",
-		.rx_flow	= 22,
-		.phy_addr	= 0,
-		.slave_port	= 1,
-		.sgmii_link_type = SGMII_LINK_MAC_PHY,
-		.phy_if          = PHY_INTERFACE_MODE_SGMII,
-	},
-	{
-		.int_name	= "K2HK_EMAC1",
-		.rx_flow	= 23,
-		.phy_addr	= 1,
-		.slave_port	= 2,
-		.sgmii_link_type = SGMII_LINK_MAC_PHY,
-		.phy_if          = PHY_INTERFACE_MODE_SGMII,
-	},
-	{
-		.int_name	= "K2HK_EMAC2",
-		.rx_flow	= 24,
-		.phy_addr	= 2,
-		.slave_port	= 3,
-		.sgmii_link_type = SGMII_LINK_MAC_MAC_FORCED,
-		.phy_if          = PHY_INTERFACE_MODE_SGMII,
-	},
-	{
-		.int_name	= "K2HK_EMAC3",
-		.rx_flow	= 25,
-		.phy_addr	= 3,
-		.slave_port	= 4,
-		.sgmii_link_type = SGMII_LINK_MAC_MAC_FORCED,
-		.phy_if          = PHY_INTERFACE_MODE_SGMII,
-	},
-};
-
-int get_num_eth_ports(void)
-{
-	return sizeof(eth_priv_cfg) / sizeof(struct eth_priv_t);
-}
-#endif
-
 #ifdef CONFIG_BOARD_EARLY_INIT_F
 int board_early_init_f(void)
 {
diff --git a/board/ti/ks2_evm/board_k2l.c b/board/ti/ks2_evm/board_k2l.c
index c28fad5..e49d8b3 100644
--- a/board/ti/ks2_evm/board_k2l.c
+++ b/board/ti/ks2_evm/board_k2l.c
@@ -84,48 +84,6 @@
 	return data;
 }
 
-#ifdef CONFIG_DRIVER_TI_KEYSTONE_NET
-struct eth_priv_t eth_priv_cfg[] = {
-	{
-		.int_name        = "K2L_EMAC",
-		.rx_flow         = 0,
-		.phy_addr        = 0,
-		.slave_port      = 1,
-		.sgmii_link_type = SGMII_LINK_MAC_PHY,
-		.phy_if          = PHY_INTERFACE_MODE_SGMII,
-	},
-	{
-		.int_name        = "K2L_EMAC1",
-		.rx_flow         = 8,
-		.phy_addr        = 1,
-		.slave_port      = 2,
-		.sgmii_link_type = SGMII_LINK_MAC_PHY,
-		.phy_if          = PHY_INTERFACE_MODE_SGMII,
-	},
-	{
-		.int_name        = "K2L_EMAC2",
-		.rx_flow         = 16,
-		.phy_addr        = 2,
-		.slave_port      = 3,
-		.sgmii_link_type = SGMII_LINK_MAC_MAC_FORCED,
-		.phy_if          = PHY_INTERFACE_MODE_SGMII,
-	},
-	{
-		.int_name        = "K2L_EMAC3",
-		.rx_flow         = 32,
-		.phy_addr        = 3,
-		.slave_port      = 4,
-		.sgmii_link_type = SGMII_LINK_MAC_MAC_FORCED,
-		.phy_if          = PHY_INTERFACE_MODE_SGMII,
-	},
-};
-
-int get_num_eth_ports(void)
-{
-	return sizeof(eth_priv_cfg) / sizeof(struct eth_priv_t);
-}
-#endif
-
 #ifdef CONFIG_BOARD_EARLY_INIT_F
 int board_early_init_f(void)
 {
diff --git a/configs/evb-ast2500_defconfig b/configs/evb-ast2500_defconfig
index 88230f4..32581f5 100644
--- a/configs/evb-ast2500_defconfig
+++ b/configs/evb-ast2500_defconfig
@@ -25,3 +25,11 @@
 CONFIG_SYSRESET=y
 CONFIG_TIMER=y
 CONFIG_WDT=y
+CONFIG_NETDEVICES=y
+CONFIG_PHY=y
+CONFIG_DM_ETH=y
+CONFIG_FTGMAC100=y
+CONFIG_PHY_REALTEK=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MII=y
diff --git a/configs/k2e_evm_defconfig b/configs/k2e_evm_defconfig
index d744cb1..67b1f30 100644
--- a/configs/k2e_evm_defconfig
+++ b/configs/k2e_evm_defconfig
@@ -56,3 +56,4 @@
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
 CONFIG_USB_STORAGE=y
+CONFIG_DRIVER_TI_KEYSTONE_NET=y
diff --git a/configs/k2e_hs_evm_defconfig b/configs/k2e_hs_evm_defconfig
index 87faf3d..1abda84 100644
--- a/configs/k2e_hs_evm_defconfig
+++ b/configs/k2e_hs_evm_defconfig
@@ -49,3 +49,4 @@
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
 CONFIG_USB_STORAGE=y
+CONFIG_DRIVER_TI_KEYSTONE_NET=y
diff --git a/configs/k2g_evm_defconfig b/configs/k2g_evm_defconfig
index a96029c..bc4b92b 100644
--- a/configs/k2g_evm_defconfig
+++ b/configs/k2g_evm_defconfig
@@ -60,3 +60,4 @@
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
 CONFIG_USB_STORAGE=y
+CONFIG_DRIVER_TI_KEYSTONE_NET=y
diff --git a/configs/k2g_hs_evm_defconfig b/configs/k2g_hs_evm_defconfig
index 9e75500..66d8220 100644
--- a/configs/k2g_hs_evm_defconfig
+++ b/configs/k2g_hs_evm_defconfig
@@ -53,3 +53,4 @@
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
 CONFIG_USB_STORAGE=y
+CONFIG_DRIVER_TI_KEYSTONE_NET=y
diff --git a/configs/k2hk_evm_defconfig b/configs/k2hk_evm_defconfig
index 8c7d362..f66d922 100644
--- a/configs/k2hk_evm_defconfig
+++ b/configs/k2hk_evm_defconfig
@@ -56,3 +56,4 @@
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
 CONFIG_USB_STORAGE=y
+CONFIG_DRIVER_TI_KEYSTONE_NET=y
diff --git a/configs/k2hk_hs_evm_defconfig b/configs/k2hk_hs_evm_defconfig
index c8f4bbe..dd91a51 100644
--- a/configs/k2hk_hs_evm_defconfig
+++ b/configs/k2hk_hs_evm_defconfig
@@ -49,3 +49,4 @@
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
 CONFIG_USB_STORAGE=y
+CONFIG_DRIVER_TI_KEYSTONE_NET=y
diff --git a/configs/k2l_evm_defconfig b/configs/k2l_evm_defconfig
index dd91aa5..4f04caa 100644
--- a/configs/k2l_evm_defconfig
+++ b/configs/k2l_evm_defconfig
@@ -56,3 +56,4 @@
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
 CONFIG_USB_STORAGE=y
+CONFIG_DRIVER_TI_KEYSTONE_NET=y
diff --git a/configs/k2l_hs_evm_defconfig b/configs/k2l_hs_evm_defconfig
index ac400e4..9ce23de 100644
--- a/configs/k2l_hs_evm_defconfig
+++ b/configs/k2l_hs_evm_defconfig
@@ -48,3 +48,4 @@
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
 CONFIG_USB_STORAGE=y
+CONFIG_DRIVER_TI_KEYSTONE_NET=y
diff --git a/doc/device-tree-bindings/net/mediatek,mt7628-eth.txt b/doc/device-tree-bindings/net/mediatek,mt7628-eth.txt
new file mode 100644
index 0000000..ec97504
--- /dev/null
+++ b/doc/device-tree-bindings/net/mediatek,mt7628-eth.txt
@@ -0,0 +1,17 @@
+* MediaTek Frame Engine Ethernet controller
+
+Required properties:
+- compatible: should be "mediatek,mt7628-eth"
+- reg: address and length of the register set for the frame
+       engine ethernet controller and the internal switch.
+- syscon: phandle to the system controller
+
+Example:
+
+eth@10100000 {
+	compatible = "mediatek,mt7628-eth";
+	reg = <0x10100000 0x10000
+	       0x10110000 0x8000>;
+
+	syscon = <&sysc>;
+};
diff --git a/drivers/clk/aspeed/clk_ast2500.c b/drivers/clk/aspeed/clk_ast2500.c
index 5264700..dbee13a 100644
--- a/drivers/clk/aspeed/clk_ast2500.c
+++ b/drivers/clk/aspeed/clk_ast2500.c
@@ -165,6 +165,35 @@
 	return rate;
 }
 
+struct ast2500_clock_config {
+	ulong input_rate;
+	ulong rate;
+	struct ast2500_div_config cfg;
+};
+
+static const struct ast2500_clock_config ast2500_clock_config_defaults[] = {
+	{ 24000000, 250000000, { .num = 124, .denum = 1, .post_div = 5 } },
+};
+
+static bool ast2500_get_clock_config_default(ulong input_rate,
+					     ulong requested_rate,
+					     struct ast2500_div_config *cfg)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(ast2500_clock_config_defaults); i++) {
+		const struct ast2500_clock_config *default_cfg =
+			&ast2500_clock_config_defaults[i];
+		if (default_cfg->input_rate == input_rate &&
+		    default_cfg->rate == requested_rate) {
+			*cfg = default_cfg->cfg;
+			return true;
+		}
+	}
+
+	return false;
+}
+
 /*
  * @input_rate - the rate of input clock in Hz
  * @requested_rate - desired output rate in Hz
@@ -189,6 +218,12 @@
 	ulong delta = rate_khz;
 	ulong new_rate_khz = 0;
 
+	/*
+	 * Look for a well known frequency first.
+	 */
+	if (ast2500_get_clock_config_default(input_rate, requested_rate, cfg))
+		return requested_rate;
+
 	for (; it.denum <= max_vals.denum; ++it.denum) {
 		for (it.post_div = 0; it.post_div <= max_vals.post_div;
 		     ++it.post_div) {
@@ -318,6 +353,9 @@
 	/*
 	 * The values and the meaning of the next three
 	 * parameters are undocumented. Taken from Aspeed SDK.
+	 *
+	 * TODO(clg@kaod.org): the SIP and SIC values depend on the
+	 * Numerator value
 	 */
 	const u32 d2_pll_ext_param = 0x2c;
 	const u32 d2_pll_sip = 0x11;
@@ -411,6 +449,7 @@
 		break;
 	case PLL_D2PLL:
 		ast2500_configure_d2pll(priv->scu, D2PLL_DEFAULT_RATE);
+		break;
 	default:
 		return -ENOENT;
 	}
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 3968743..8fb365f 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -11,13 +11,6 @@
 	  This is currently implemented in net/eth-uclass.c
 	  Look in include/net.h for details.
 
-config DRIVER_TI_CPSW
-	bool "TI Common Platform Ethernet Switch"
-	select PHYLIB
-	help
-	  This driver supports the TI three port switch gigabit ethernet
-	  subsystem found in the TI SoCs.
-
 menuconfig NETDEVICES
 	bool "Network device support"
 	depends on NET
@@ -186,6 +179,32 @@
 	help
 	  This MAC is present in Andestech SoCs.
 
+config FTGMAC100
+	bool "Ftgmac100 Ethernet Support"
+	depends on DM_ETH
+	select PHYLIB
+	help
+	  This driver supports the Faraday's FTGMAC100 Gigabit SoC
+	  Ethernet controller that can be found on Aspeed SoCs (which
+	  include NCSI).
+
+	  It is fully compliant with IEEE 802.3 specification for
+	  10/100 Mbps Ethernet and IEEE 802.3z specification for 1000
+	  Mbps Ethernet and includes Reduced Media Independent
+	  Interface (RMII) and Reduced Gigabit Media Independent
+	  Interface (RGMII) interfaces. It adopts an AHB bus interface
+	  and integrates a link list DMA engine with direct M-Bus
+	  accesses for transmitting and receiving packets. It has
+	  independent TX/RX fifos, supports half and full duplex (1000
+	  Mbps mode only supports full duplex), flow control for full
+	  duplex and backpressure for half duplex.
+
+	  The FTGMAC100 also implements IP, TCP, UDP checksum offloads
+	  and supports IEEE 802.1Q VLAN tag insertion and removal. It
+	  offers high-priority transmit queue for QoS and CoS
+	  applications.
+
+
 config MVGBE
 	bool "Marvell Orion5x/Kirkwood network interface support"
 	depends on KIRKWOOD || ORION5X
@@ -227,6 +246,13 @@
 	  The Cadence MACB ethernet interface was used on Zynq platform.
 	  Say Y to enable support for the MACB/GEM in Zynq chip.
 
+config MT7628_ETH
+	bool "MediaTek MT7628 Ethernet Interface"
+	depends on ARCH_MT7620
+	help
+	  The MediaTek MT7628 ethernet interface is used on MT7628 and
+	  MT7688 based boards.
+
 config PCH_GBE
 	bool "Intel Platform Controller Hub EG20T GMAC driver"
 	depends on DM_ETH && DM_PCI
@@ -322,10 +348,7 @@
 	help
 	  This driver supports the Ethernet for Renesas SH and ARM SoCs.
 
-config DRIVER_TI_EMAC
-	bool "TI Davinci EMAC"
-	help
-	   Support for davinci emac
+source "drivers/net/ti/Kconfig"
 
 config XILINX_AXIEMAC
 	depends on DM_ETH && (MICROBLAZE || ARCH_ZYNQ || ARCH_ZYNQMP)
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 48a2878..99056aa 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -30,13 +30,13 @@
 obj-$(CONFIG_FTMAC110) += ftmac110.o
 obj-$(CONFIG_FTMAC100) += ftmac100.o
 obj-$(CONFIG_GMAC_ROCKCHIP) += gmac_rockchip.o
-obj-$(CONFIG_DRIVER_TI_KEYSTONE_NET) += keystone_net.o
 obj-$(CONFIG_KS8851_MLL) += ks8851_mll.o
 obj-$(CONFIG_LAN91C96) += lan91c96.o
 obj-$(CONFIG_LPC32XX_ETH) += lpc32xx_eth.o
 obj-$(CONFIG_MACB) += macb.o
 obj-$(CONFIG_MCFFEC) += mcffec.o mcfmii.o
 obj-$(CONFIG_MPC8XX_FEC) += mpc8xx_fec.o
+obj-$(CONFIG_MT7628_ETH) += mt7628-eth.o
 obj-$(CONFIG_MVGBE) += mvgbe.o
 obj-$(CONFIG_MVNETA) += mvneta.o
 obj-$(CONFIG_MVPP2) += mvpp2.o
@@ -56,9 +56,7 @@
 obj-$(CONFIG_RENESAS_RAVB) += ravb.o
 obj-$(CONFIG_SMC91111) += smc91111.o
 obj-$(CONFIG_SMC911X) += smc911x.o
-obj-$(CONFIG_DRIVER_TI_EMAC) += davinci_emac.o
 obj-$(CONFIG_TSEC_ENET) += tsec.o fsl_mdio.o
-obj-$(CONFIG_DRIVER_TI_CPSW) += cpsw.o cpsw-common.o
 obj-$(CONFIG_FMAN_ENET) += fsl_mdio.o
 obj-$(CONFIG_ULI526X) += uli526x.o
 obj-$(CONFIG_VSC7385_ENET) += vsc7385.o
@@ -73,3 +71,4 @@
 obj-$(CONFIG_DWC_ETH_QOS) += dwc_eth_qos.o
 obj-$(CONFIG_FSL_PFE) += pfe_eth/
 obj-$(CONFIG_SNI_AVE) += sni_ave.o
+obj-y += ti/
diff --git a/drivers/net/ftgmac100.c b/drivers/net/ftgmac100.c
index c996f5f..92c38a8 100644
--- a/drivers/net/ftgmac100.c
+++ b/drivers/net/ftgmac100.c
@@ -7,321 +7,239 @@
  *
  * (C) Copyright 2010 Andes Technology
  * Macpaul Lin <macpaul@andestech.com>
+ *
+ * Copyright (C) 2018, IBM Corporation.
  */
 
-#include <config.h>
-#include <common.h>
-#include <malloc.h>
+#include <clk.h>
+#include <dm.h>
+#include <miiphy.h>
 #include <net.h>
-#include <asm/io.h>
-#include <asm/dma-mapping.h>
-#include <linux/mii.h>
+#include <wait_bit.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
 
 #include "ftgmac100.h"
 
-#define ETH_ZLEN	60
-#define CFG_XBUF_SIZE	1536
+/* Min frame ethernet frame size without FCS */
+#define ETH_ZLEN			60
 
-/* RBSR - hw default init value is also 0x640 */
-#define RBSR_DEFAULT_VALUE	0x640
+/* Receive Buffer Size Register - HW default is 0x640 */
+#define FTGMAC100_RBSR_DEFAULT		0x640
 
 /* PKTBUFSTX/PKTBUFSRX must both be power of 2 */
 #define PKTBUFSTX	4	/* must be power of 2 */
 
+/* Timeout for transmit */
+#define FTGMAC100_TX_TIMEOUT_MS		1000
+
+/* Timeout for a mdio read/write operation */
+#define FTGMAC100_MDIO_TIMEOUT_USEC	10000
+
+/*
+ * MDC clock cycle threshold
+ *
+ * 20us * 100 = 2ms > (1 / 2.5Mhz) * 0x34
+ */
+#define MDC_CYCTHR			0x34
+
+/*
+ * ftgmac100 model variants
+ */
+enum ftgmac100_model {
+	FTGMAC100_MODEL_FARADAY,
+	FTGMAC100_MODEL_ASPEED,
+};
+
+/**
+ * struct ftgmac100_data - private data for the FTGMAC100 driver
+ *
+ * @iobase: The base address of the hardware registers
+ * @txdes: The array of transmit descriptors
+ * @rxdes: The array of receive descriptors
+ * @tx_index: Transmit descriptor index in @txdes
+ * @rx_index: Receive descriptor index in @rxdes
+ * @phy_addr: The PHY interface address to use
+ * @phydev: The PHY device backing the MAC
+ * @bus: The mdio bus
+ * @phy_mode: The mode of the PHY interface (rgmii, rmii, ...)
+ * @max_speed: Maximum speed of Ethernet connection supported by MAC
+ * @clks: The bulk of clocks assigned to the device in the DT
+ * @rxdes0_edorr_mask: The bit number identifying the end of the RX ring buffer
+ * @txdes0_edotr_mask: The bit number identifying the end of the TX ring buffer
+ */
 struct ftgmac100_data {
-	ulong txdes_dma;
-	struct ftgmac100_txdes *txdes;
-	ulong rxdes_dma;
-	struct ftgmac100_rxdes *rxdes;
+	struct ftgmac100 *iobase;
+
+	struct ftgmac100_txdes txdes[PKTBUFSTX];
+	struct ftgmac100_rxdes rxdes[PKTBUFSRX];
 	int tx_index;
 	int rx_index;
-	int phy_addr;
+
+	u32 phy_addr;
+	struct phy_device *phydev;
+	struct mii_dev *bus;
+	u32 phy_mode;
+	u32 max_speed;
+
+	struct clk_bulk clks;
+
+	/* End of RX/TX ring buffer bits. Depend on model */
+	u32 rxdes0_edorr_mask;
+	u32 txdes0_edotr_mask;
 };
 
 /*
  * struct mii_bus functions
  */
-static int ftgmac100_mdiobus_read(struct eth_device *dev, int phy_addr,
-	int regnum)
+static int ftgmac100_mdio_read(struct mii_dev *bus, int phy_addr, int dev_addr,
+			       int reg_addr)
 {
-	struct ftgmac100 *ftgmac100 = (struct ftgmac100 *)dev->iobase;
-	int phycr;
-	int i;
-
-	phycr = readl(&ftgmac100->phycr);
-
-	/* preserve MDC cycle threshold */
-	phycr &= FTGMAC100_PHYCR_MDC_CYCTHR_MASK;
-
-	phycr |= FTGMAC100_PHYCR_PHYAD(phy_addr)
-	      |  FTGMAC100_PHYCR_REGAD(regnum)
-	      |  FTGMAC100_PHYCR_MIIRD;
-
-	writel(phycr, &ftgmac100->phycr);
-
-	for (i = 0; i < 10; i++) {
-		phycr = readl(&ftgmac100->phycr);
-
-		if ((phycr & FTGMAC100_PHYCR_MIIRD) == 0) {
-			int data;
-
-			data = readl(&ftgmac100->phydata);
-			return FTGMAC100_PHYDATA_MIIRDATA(data);
-		}
-
-		mdelay(10);
-	}
-
-	debug("mdio read timed out\n");
-	return -1;
-}
-
-static int ftgmac100_mdiobus_write(struct eth_device *dev, int phy_addr,
-	int regnum, u16 value)
-{
-	struct ftgmac100 *ftgmac100 = (struct ftgmac100 *)dev->iobase;
+	struct ftgmac100_data *priv = bus->priv;
+	struct ftgmac100 *ftgmac100 = priv->iobase;
 	int phycr;
 	int data;
-	int i;
+	int ret;
 
-	phycr = readl(&ftgmac100->phycr);
+	phycr = FTGMAC100_PHYCR_MDC_CYCTHR(MDC_CYCTHR) |
+		FTGMAC100_PHYCR_PHYAD(phy_addr) |
+		FTGMAC100_PHYCR_REGAD(reg_addr) |
+		FTGMAC100_PHYCR_MIIRD;
+	writel(phycr, &ftgmac100->phycr);
 
-	/* preserve MDC cycle threshold */
-	phycr &= FTGMAC100_PHYCR_MDC_CYCTHR_MASK;
+	ret = readl_poll_timeout(&ftgmac100->phycr, phycr,
+				 !(phycr & FTGMAC100_PHYCR_MIIRD),
+				 FTGMAC100_MDIO_TIMEOUT_USEC);
+	if (ret) {
+		pr_err("%s: mdio read failed (phy:%d reg:%x)\n",
+		       priv->phydev->dev->name, phy_addr, reg_addr);
+		return ret;
+	}
 
-	phycr |= FTGMAC100_PHYCR_PHYAD(phy_addr)
-	      |  FTGMAC100_PHYCR_REGAD(regnum)
-	      |  FTGMAC100_PHYCR_MIIWR;
+	data = readl(&ftgmac100->phydata);
 
+	return FTGMAC100_PHYDATA_MIIRDATA(data);
+}
+
+static int ftgmac100_mdio_write(struct mii_dev *bus, int phy_addr, int dev_addr,
+				int reg_addr, u16 value)
+{
+	struct ftgmac100_data *priv = bus->priv;
+	struct ftgmac100 *ftgmac100 = priv->iobase;
+	int phycr;
+	int data;
+	int ret;
+
+	phycr = FTGMAC100_PHYCR_MDC_CYCTHR(MDC_CYCTHR) |
+		FTGMAC100_PHYCR_PHYAD(phy_addr) |
+		FTGMAC100_PHYCR_REGAD(reg_addr) |
+		FTGMAC100_PHYCR_MIIWR;
 	data = FTGMAC100_PHYDATA_MIIWDATA(value);
 
 	writel(data, &ftgmac100->phydata);
 	writel(phycr, &ftgmac100->phycr);
 
-	for (i = 0; i < 10; i++) {
-		phycr = readl(&ftgmac100->phycr);
-
-		if ((phycr & FTGMAC100_PHYCR_MIIWR) == 0) {
-			debug("(phycr & FTGMAC100_PHYCR_MIIWR) == 0: " \
-				"phy_addr: %x\n", phy_addr);
-			return 0;
-		}
-
-		mdelay(1);
+	ret = readl_poll_timeout(&ftgmac100->phycr, phycr,
+				 !(phycr & FTGMAC100_PHYCR_MIIWR),
+				 FTGMAC100_MDIO_TIMEOUT_USEC);
+	if (ret) {
+		pr_err("%s: mdio write failed (phy:%d reg:%x)\n",
+		       priv->phydev->dev->name, phy_addr, reg_addr);
 	}
 
-	debug("mdio write timed out\n");
-	return -1;
+	return ret;
 }
 
-int ftgmac100_phy_read(struct eth_device *dev, int addr, int reg, u16 *value)
+static int ftgmac100_mdio_init(struct udevice *dev)
 {
-	*value = ftgmac100_mdiobus_read(dev , addr, reg);
+	struct ftgmac100_data *priv = dev_get_priv(dev);
+	struct mii_dev *bus;
+	int ret;
 
-	if (*value == -1)
-		return -1;
+	bus = mdio_alloc();
+	if (!bus)
+		return -ENOMEM;
+
+	bus->read  = ftgmac100_mdio_read;
+	bus->write = ftgmac100_mdio_write;
+	bus->priv  = priv;
+
+	ret = mdio_register_seq(bus, dev->seq);
+	if (ret) {
+		free(bus);
+		return ret;
+	}
+
+	priv->bus = bus;
 
 	return 0;
 }
 
-int  ftgmac100_phy_write(struct eth_device *dev, int addr, int reg, u16 value)
+static int ftgmac100_phy_adjust_link(struct ftgmac100_data *priv)
 {
-	if (ftgmac100_mdiobus_write(dev, addr, reg, value) == -1)
-		return -1;
+	struct ftgmac100 *ftgmac100 = priv->iobase;
+	struct phy_device *phydev = priv->phydev;
+	u32 maccr;
 
-	return 0;
-}
-
-static int ftgmac100_phy_reset(struct eth_device *dev)
-{
-	struct ftgmac100_data *priv = dev->priv;
-	int i;
-	u16 status, adv;
-
-	adv = ADVERTISE_CSMA | ADVERTISE_ALL;
-
-	ftgmac100_phy_write(dev, priv->phy_addr, MII_ADVERTISE, adv);
-
-	printf("%s: Starting autonegotiation...\n", dev->name);
-
-	ftgmac100_phy_write(dev, priv->phy_addr,
-		MII_BMCR, (BMCR_ANENABLE | BMCR_ANRESTART));
-
-	for (i = 0; i < 100000 / 100; i++) {
-		ftgmac100_phy_read(dev, priv->phy_addr, MII_BMSR, &status);
-
-		if (status & BMSR_ANEGCOMPLETE)
-			break;
-		mdelay(1);
+	if (!phydev->link) {
+		dev_err(phydev->dev, "No link\n");
+		return -EREMOTEIO;
 	}
 
-	if (status & BMSR_ANEGCOMPLETE) {
-		printf("%s: Autonegotiation complete\n", dev->name);
-	} else {
-		printf("%s: Autonegotiation timed out (status=0x%04x)\n",
-		       dev->name, status);
-		return 0;
-	}
-
-	return 1;
-}
-
-static int ftgmac100_phy_init(struct eth_device *dev)
-{
-	struct ftgmac100_data *priv = dev->priv;
-
-	int phy_addr;
-	u16 phy_id, status, adv, lpa, stat_ge;
-	int media, speed, duplex;
-	int i;
-
-	/* Check if the PHY is up to snuff... */
-	for (phy_addr = 0; phy_addr < CONFIG_PHY_MAX_ADDR; phy_addr++) {
-
-		ftgmac100_phy_read(dev, phy_addr, MII_PHYSID1, &phy_id);
-
-		/*
-		 * When it is unable to found PHY,
-		 * the interface usually return 0xffff or 0x0000
-		 */
-		if (phy_id != 0xffff && phy_id != 0x0) {
-			printf("%s: found PHY at 0x%02x\n",
-				dev->name, phy_addr);
-			priv->phy_addr = phy_addr;
-			break;
-		}
-	}
-
-	if (phy_id == 0xffff || phy_id == 0x0) {
-		printf("%s: no PHY present\n", dev->name);
-		return 0;
-	}
-
-	ftgmac100_phy_read(dev, priv->phy_addr, MII_BMSR, &status);
-
-	if (!(status & BMSR_LSTATUS)) {
-		/* Try to re-negotiate if we don't have link already. */
-		ftgmac100_phy_reset(dev);
-
-		for (i = 0; i < 100000 / 100; i++) {
-			ftgmac100_phy_read(dev, priv->phy_addr,
-				MII_BMSR, &status);
-			if (status & BMSR_LSTATUS)
-				break;
-			udelay(100);
-		}
-	}
-
-	if (!(status & BMSR_LSTATUS)) {
-		printf("%s: link down\n", dev->name);
-		return 0;
-	}
-
-#ifdef CONFIG_FTGMAC100_EGIGA
-	/* 1000 Base-T Status Register */
-	ftgmac100_phy_read(dev, priv->phy_addr,
-		MII_STAT1000, &stat_ge);
-
-	speed = (stat_ge & (LPA_1000FULL | LPA_1000HALF)
-		 ? 1 : 0);
-
-	duplex = ((stat_ge & LPA_1000FULL)
-		 ? 1 : 0);
-
-	if (speed) { /* Speed is 1000 */
-		printf("%s: link up, 1000bps %s-duplex\n",
-			dev->name, duplex ? "full" : "half");
-		return 0;
-	}
-#endif
-
-	ftgmac100_phy_read(dev, priv->phy_addr, MII_ADVERTISE, &adv);
-	ftgmac100_phy_read(dev, priv->phy_addr, MII_LPA, &lpa);
-
-	media = mii_nway_result(lpa & adv);
-	speed = (media & (ADVERTISE_100FULL | ADVERTISE_100HALF) ? 1 : 0);
-	duplex = (media & ADVERTISE_FULL) ? 1 : 0;
-
-	printf("%s: link up, %sMbps %s-duplex\n",
-	       dev->name, speed ? "100" : "10", duplex ? "full" : "half");
-
-	return 1;
-}
-
-static int ftgmac100_update_link_speed(struct eth_device *dev)
-{
-	struct ftgmac100 *ftgmac100 = (struct ftgmac100 *)dev->iobase;
-	struct ftgmac100_data *priv = dev->priv;
-
-	unsigned short stat_fe;
-	unsigned short stat_ge;
-	unsigned int maccr;
-
-#ifdef CONFIG_FTGMAC100_EGIGA
-	/* 1000 Base-T Status Register */
-	ftgmac100_phy_read(dev, priv->phy_addr, MII_STAT1000, &stat_ge);
-#endif
-
-	ftgmac100_phy_read(dev, priv->phy_addr, MII_BMSR, &stat_fe);
-
-	if (!(stat_fe & BMSR_LSTATUS))	/* link status up? */
-		return 0;
-
 	/* read MAC control register and clear related bits */
 	maccr = readl(&ftgmac100->maccr) &
 		~(FTGMAC100_MACCR_GIGA_MODE |
 		  FTGMAC100_MACCR_FAST_MODE |
 		  FTGMAC100_MACCR_FULLDUP);
 
-#ifdef CONFIG_FTGMAC100_EGIGA
-	if (stat_ge & LPA_1000FULL) {
-		/* set gmac for 1000BaseTX and Full Duplex */
-		maccr |= FTGMAC100_MACCR_GIGA_MODE | FTGMAC100_MACCR_FULLDUP;
-	}
-
-	if (stat_ge & LPA_1000HALF) {
-		/* set gmac for 1000BaseTX and Half Duplex */
+	if (phy_interface_is_rgmii(phydev) && phydev->speed == 1000)
 		maccr |= FTGMAC100_MACCR_GIGA_MODE;
-	}
-#endif
 
-	if (stat_fe & BMSR_100FULL) {
-		/* set MII for 100BaseTX and Full Duplex */
-		maccr |= FTGMAC100_MACCR_FAST_MODE | FTGMAC100_MACCR_FULLDUP;
-	}
-
-	if (stat_fe & BMSR_10FULL) {
-		/* set MII for 10BaseT and Full Duplex */
-		maccr |= FTGMAC100_MACCR_FULLDUP;
-	}
-
-	if (stat_fe & BMSR_100HALF) {
-		/* set MII for 100BaseTX and Half Duplex */
+	if (phydev->speed == 100)
 		maccr |= FTGMAC100_MACCR_FAST_MODE;
-	}
 
-	if (stat_fe & BMSR_10HALF) {
-		/* set MII for 10BaseT and Half Duplex */
-		/* we have already clear these bits, do nothing */
-		;
-	}
+	if (phydev->duplex)
+		maccr |= FTGMAC100_MACCR_FULLDUP;
 
 	/* update MII config into maccr */
 	writel(maccr, &ftgmac100->maccr);
 
-	return 1;
+	return 0;
+}
+
+static int ftgmac100_phy_init(struct udevice *dev)
+{
+	struct ftgmac100_data *priv = dev_get_priv(dev);
+	struct phy_device *phydev;
+	int ret;
+
+	phydev = phy_connect(priv->bus, priv->phy_addr, dev, priv->phy_mode);
+	if (!phydev)
+		return -ENODEV;
+
+	phydev->supported &= PHY_GBIT_FEATURES;
+	if (priv->max_speed) {
+		ret = phy_set_supported(phydev, priv->max_speed);
+		if (ret)
+			return ret;
+	}
+	phydev->advertising = phydev->supported;
+	priv->phydev = phydev;
+	phy_config(phydev);
+
+	return 0;
 }
 
 /*
  * Reset MAC
  */
-static void ftgmac100_reset(struct eth_device *dev)
+static void ftgmac100_reset(struct ftgmac100_data *priv)
 {
-	struct ftgmac100 *ftgmac100 = (struct ftgmac100 *)dev->iobase;
+	struct ftgmac100 *ftgmac100 = priv->iobase;
 
 	debug("%s()\n", __func__);
 
-	writel(FTGMAC100_MACCR_SW_RST, &ftgmac100->maccr);
+	setbits_le32(&ftgmac100->maccr, FTGMAC100_MACCR_SW_RST);
 
 	while (readl(&ftgmac100->maccr) & FTGMAC100_MACCR_SW_RST)
 		;
@@ -330,10 +248,10 @@
 /*
  * Set MAC address
  */
-static void ftgmac100_set_mac(struct eth_device *dev,
-	const unsigned char *mac)
+static int ftgmac100_set_mac(struct ftgmac100_data *priv,
+			     const unsigned char *mac)
 {
-	struct ftgmac100 *ftgmac100 = (struct ftgmac100 *)dev->iobase;
+	struct ftgmac100 *ftgmac100 = priv->iobase;
 	unsigned int maddr = mac[0] << 8 | mac[1];
 	unsigned int laddr = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
 
@@ -341,61 +259,42 @@
 
 	writel(maddr, &ftgmac100->mac_madr);
 	writel(laddr, &ftgmac100->mac_ladr);
-}
 
-static void ftgmac100_set_mac_from_env(struct eth_device *dev)
-{
-	eth_env_get_enetaddr("ethaddr", dev->enetaddr);
-
-	ftgmac100_set_mac(dev, dev->enetaddr);
+	return 0;
 }
 
 /*
  * disable transmitter, receiver
  */
-static void ftgmac100_halt(struct eth_device *dev)
+static void ftgmac100_stop(struct udevice *dev)
 {
-	struct ftgmac100 *ftgmac100 = (struct ftgmac100 *)dev->iobase;
+	struct ftgmac100_data *priv = dev_get_priv(dev);
+	struct ftgmac100 *ftgmac100 = priv->iobase;
 
 	debug("%s()\n", __func__);
 
 	writel(0, &ftgmac100->maccr);
+
+	phy_shutdown(priv->phydev);
 }
 
-static int ftgmac100_init(struct eth_device *dev, bd_t *bd)
+static int ftgmac100_start(struct udevice *dev)
 {
-	struct ftgmac100 *ftgmac100 = (struct ftgmac100 *)dev->iobase;
-	struct ftgmac100_data *priv = dev->priv;
-	struct ftgmac100_txdes *txdes;
-	struct ftgmac100_rxdes *rxdes;
+	struct eth_pdata *plat = dev_get_platdata(dev);
+	struct ftgmac100_data *priv = dev_get_priv(dev);
+	struct ftgmac100 *ftgmac100 = priv->iobase;
+	struct phy_device *phydev = priv->phydev;
 	unsigned int maccr;
-	void *buf;
+	ulong start, end;
+	int ret;
 	int i;
 
 	debug("%s()\n", __func__);
 
-	if (!priv->txdes) {
-		txdes = dma_alloc_coherent(
-			sizeof(*txdes) * PKTBUFSTX, &priv->txdes_dma);
-		if (!txdes)
-			panic("ftgmac100: out of memory\n");
-		memset(txdes, 0, sizeof(*txdes) * PKTBUFSTX);
-		priv->txdes = txdes;
-	}
-	txdes = priv->txdes;
-
-	if (!priv->rxdes) {
-		rxdes = dma_alloc_coherent(
-			sizeof(*rxdes) * PKTBUFSRX, &priv->rxdes_dma);
-		if (!rxdes)
-			panic("ftgmac100: out of memory\n");
-		memset(rxdes, 0, sizeof(*rxdes) * PKTBUFSRX);
-		priv->rxdes = rxdes;
-	}
-	rxdes = priv->rxdes;
+	ftgmac100_reset(priv);
 
 	/* set the ethernet address */
-	ftgmac100_set_mac_from_env(dev);
+	ftgmac100_set_mac(priv, plat->enetaddr);
 
 	/* disable all interrupts */
 	writel(0, &ftgmac100->ier);
@@ -404,42 +303,37 @@
 	priv->tx_index = 0;
 	priv->rx_index = 0;
 
-	txdes[PKTBUFSTX - 1].txdes0	= FTGMAC100_TXDES0_EDOTR;
-	rxdes[PKTBUFSRX - 1].rxdes0	= FTGMAC100_RXDES0_EDORR;
-
 	for (i = 0; i < PKTBUFSTX; i++) {
-		/* TXBUF_BADR */
-		if (!txdes[i].txdes2) {
-			buf = memalign(ARCH_DMA_MINALIGN, CFG_XBUF_SIZE);
-			if (!buf)
-				panic("ftgmac100: out of memory\n");
-			txdes[i].txdes3 = virt_to_phys(buf);
-			txdes[i].txdes2 = (uint)buf;
-		}
-		txdes[i].txdes1 = 0;
+		priv->txdes[i].txdes3 = 0;
+		priv->txdes[i].txdes0 = 0;
 	}
+	priv->txdes[PKTBUFSTX - 1].txdes0 = priv->txdes0_edotr_mask;
+
+	start = (ulong)&priv->txdes[0];
+	end = start + roundup(sizeof(priv->txdes), ARCH_DMA_MINALIGN);
+	flush_dcache_range(start, end);
 
 	for (i = 0; i < PKTBUFSRX; i++) {
-		/* RXBUF_BADR */
-		if (!rxdes[i].rxdes2) {
-			buf = net_rx_packets[i];
-			rxdes[i].rxdes3 = virt_to_phys(buf);
-			rxdes[i].rxdes2 = (uint)buf;
-		}
-		rxdes[i].rxdes0 &= ~FTGMAC100_RXDES0_RXPKT_RDY;
+		priv->rxdes[i].rxdes3 = (unsigned int)net_rx_packets[i];
+		priv->rxdes[i].rxdes0 = 0;
 	}
+	priv->rxdes[PKTBUFSRX - 1].rxdes0 = priv->rxdes0_edorr_mask;
+
+	start = (ulong)&priv->rxdes[0];
+	end = start + roundup(sizeof(priv->rxdes), ARCH_DMA_MINALIGN);
+	flush_dcache_range(start, end);
 
 	/* transmit ring */
-	writel(priv->txdes_dma, &ftgmac100->txr_badr);
+	writel((u32)priv->txdes, &ftgmac100->txr_badr);
 
 	/* receive ring */
-	writel(priv->rxdes_dma, &ftgmac100->rxr_badr);
+	writel((u32)priv->rxdes, &ftgmac100->rxr_badr);
 
 	/* poll receive descriptor automatically */
 	writel(FTGMAC100_APTC_RXPOLL_CNT(1), &ftgmac100->aptc);
 
 	/* config receive buffer size register */
-	writel(FTGMAC100_RBSR_SIZE(RBSR_DEFAULT_VALUE), &ftgmac100->rbsr);
+	writel(FTGMAC100_RBSR_SIZE(FTGMAC100_RBSR_DEFAULT), &ftgmac100->rbsr);
 
 	/* enable transmitter, receiver */
 	maccr = FTGMAC100_MACCR_TXMAC_EN |
@@ -453,34 +347,67 @@
 
 	writel(maccr, &ftgmac100->maccr);
 
-	if (!ftgmac100_phy_init(dev)) {
-		if (!ftgmac100_update_link_speed(dev))
-			return -1;
+	ret = phy_startup(phydev);
+	if (ret) {
+		dev_err(phydev->dev, "Could not start PHY\n");
+		return ret;
 	}
 
+	ret = ftgmac100_phy_adjust_link(priv);
+	if (ret) {
+		dev_err(phydev->dev,  "Could not adjust link\n");
+		return ret;
+	}
+
+	printf("%s: link up, %d Mbps %s-duplex mac:%pM\n", phydev->dev->name,
+	       phydev->speed, phydev->duplex ? "full" : "half", plat->enetaddr);
+
+	return 0;
+}
+
+static int ftgmac100_free_pkt(struct udevice *dev, uchar *packet, int length)
+{
+	struct ftgmac100_data *priv = dev_get_priv(dev);
+	struct ftgmac100_rxdes *curr_des = &priv->rxdes[priv->rx_index];
+	ulong des_start = (ulong)curr_des;
+	ulong des_end = des_start +
+		roundup(sizeof(*curr_des), ARCH_DMA_MINALIGN);
+
+	/* Release buffer to DMA and flush descriptor */
+	curr_des->rxdes0 &= ~FTGMAC100_RXDES0_RXPKT_RDY;
+	flush_dcache_range(des_start, des_end);
+
+	/* Move to next descriptor */
+	priv->rx_index = (priv->rx_index + 1) % PKTBUFSRX;
+
 	return 0;
 }
 
 /*
  * Get a data block via Ethernet
  */
-static int ftgmac100_recv(struct eth_device *dev)
+static int ftgmac100_recv(struct udevice *dev, int flags, uchar **packetp)
 {
-	struct ftgmac100_data *priv = dev->priv;
-	struct ftgmac100_rxdes *curr_des;
+	struct ftgmac100_data *priv = dev_get_priv(dev);
+	struct ftgmac100_rxdes *curr_des = &priv->rxdes[priv->rx_index];
 	unsigned short rxlen;
+	ulong des_start = (ulong)curr_des;
+	ulong des_end = des_start +
+		roundup(sizeof(*curr_des), ARCH_DMA_MINALIGN);
+	ulong data_start = curr_des->rxdes3;
+	ulong data_end;
 
-	curr_des = &priv->rxdes[priv->rx_index];
+	invalidate_dcache_range(des_start, des_end);
 
 	if (!(curr_des->rxdes0 & FTGMAC100_RXDES0_RXPKT_RDY))
-		return -1;
+		return -EAGAIN;
 
 	if (curr_des->rxdes0 & (FTGMAC100_RXDES0_RX_ERR |
 				FTGMAC100_RXDES0_CRC_ERR |
 				FTGMAC100_RXDES0_FTL |
 				FTGMAC100_RXDES0_RUNT |
 				FTGMAC100_RXDES0_RX_ODD_NB)) {
-		return -1;
+		return -EAGAIN;
 	}
 
 	rxlen = FTGMAC100_RXDES0_VDBC(curr_des->rxdes0);
@@ -488,95 +415,194 @@
 	debug("%s(): RX buffer %d, %x received\n",
 	       __func__, priv->rx_index, rxlen);
 
-	/* invalidate d-cache */
-	dma_map_single((void *)curr_des->rxdes2, rxlen, DMA_FROM_DEVICE);
+	/* Invalidate received data */
+	data_end = data_start + roundup(rxlen, ARCH_DMA_MINALIGN);
+	invalidate_dcache_range(data_start, data_end);
+	*packetp = (uchar *)data_start;
 
-	/* pass the packet up to the protocol layers. */
-	net_process_received_packet((void *)curr_des->rxdes2, rxlen);
-
-	/* release buffer to DMA */
-	curr_des->rxdes0 &= ~FTGMAC100_RXDES0_RXPKT_RDY;
-
-	priv->rx_index = (priv->rx_index + 1) % PKTBUFSRX;
-
-	return 0;
+	return rxlen;
 }
 
+static u32 ftgmac100_read_txdesc(const void *desc)
+{
+	const struct ftgmac100_txdes *txdes = desc;
+	ulong des_start = (ulong)txdes;
+	ulong des_end = des_start + roundup(sizeof(*txdes), ARCH_DMA_MINALIGN);
+
+	invalidate_dcache_range(des_start, des_end);
+
+	return txdes->txdes0;
+}
+
+BUILD_WAIT_FOR_BIT(ftgmac100_txdone, u32, ftgmac100_read_txdesc)
+
 /*
  * Send a data block via Ethernet
  */
-static int ftgmac100_send(struct eth_device *dev, void *packet, int length)
+static int ftgmac100_send(struct udevice *dev, void *packet, int length)
 {
-	struct ftgmac100 *ftgmac100 = (struct ftgmac100 *)dev->iobase;
-	struct ftgmac100_data *priv = dev->priv;
+	struct ftgmac100_data *priv = dev_get_priv(dev);
+	struct ftgmac100 *ftgmac100 = priv->iobase;
 	struct ftgmac100_txdes *curr_des = &priv->txdes[priv->tx_index];
+	ulong des_start = (ulong)curr_des;
+	ulong des_end = des_start +
+		roundup(sizeof(*curr_des), ARCH_DMA_MINALIGN);
+	ulong data_start;
+	ulong data_end;
+	int rc;
+
+	invalidate_dcache_range(des_start, des_end);
 
 	if (curr_des->txdes0 & FTGMAC100_TXDES0_TXDMA_OWN) {
-		debug("%s(): no TX descriptor available\n", __func__);
-		return -1;
+		dev_err(dev, "no TX descriptor available\n");
+		return -EPERM;
 	}
 
 	debug("%s(%x, %x)\n", __func__, (int)packet, length);
 
 	length = (length < ETH_ZLEN) ? ETH_ZLEN : length;
 
-	memcpy((void *)curr_des->txdes2, (void *)packet, length);
-	dma_map_single((void *)curr_des->txdes2, length, DMA_TO_DEVICE);
+	curr_des->txdes3 = (unsigned int)packet;
 
-	/* only one descriptor on TXBUF */
-	curr_des->txdes0 &= FTGMAC100_TXDES0_EDOTR;
+	/* Flush data to be sent */
+	data_start = curr_des->txdes3;
+	data_end = data_start + roundup(length, ARCH_DMA_MINALIGN);
+	flush_dcache_range(data_start, data_end);
+
+	/* Only one segment on TXBUF */
+	curr_des->txdes0 &= priv->txdes0_edotr_mask;
 	curr_des->txdes0 |= FTGMAC100_TXDES0_FTS |
 			    FTGMAC100_TXDES0_LTS |
 			    FTGMAC100_TXDES0_TXBUF_SIZE(length) |
 			    FTGMAC100_TXDES0_TXDMA_OWN ;
 
-	/* start transmit */
+	/* Flush modified buffer descriptor */
+	flush_dcache_range(des_start, des_end);
+
+	/* Start transmit */
 	writel(1, &ftgmac100->txpd);
 
+	rc = wait_for_bit_ftgmac100_txdone(curr_des,
+					   FTGMAC100_TXDES0_TXDMA_OWN, false,
+					   FTGMAC100_TX_TIMEOUT_MS, true);
+	if (rc)
+		return rc;
+
 	debug("%s(): packet sent\n", __func__);
 
+	/* Move to next descriptor */
 	priv->tx_index = (priv->tx_index + 1) % PKTBUFSTX;
 
 	return 0;
 }
 
-int ftgmac100_initialize(bd_t *bd)
+static int ftgmac100_write_hwaddr(struct udevice *dev)
 {
-	struct eth_device *dev;
-	struct ftgmac100_data *priv;
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct ftgmac100_data *priv = dev_get_priv(dev);
 
-	dev = malloc(sizeof *dev);
-	if (!dev) {
-		printf("%s(): failed to allocate dev\n", __func__);
+	return ftgmac100_set_mac(priv, pdata->enetaddr);
+}
+
+static int ftgmac100_ofdata_to_platdata(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct ftgmac100_data *priv = dev_get_priv(dev);
+	const char *phy_mode;
+
+	pdata->iobase = devfdt_get_addr(dev);
+	pdata->phy_interface = -1;
+	phy_mode = dev_read_string(dev, "phy-mode");
+	if (phy_mode)
+		pdata->phy_interface = phy_get_interface_by_name(phy_mode);
+	if (pdata->phy_interface == -1) {
+		dev_err(dev, "Invalid PHY interface '%s'\n", phy_mode);
+		return -EINVAL;
+	}
+
+	pdata->max_speed = dev_read_u32_default(dev, "max-speed", 0);
+
+	if (dev_get_driver_data(dev) == FTGMAC100_MODEL_ASPEED) {
+		priv->rxdes0_edorr_mask = BIT(30);
+		priv->txdes0_edotr_mask = BIT(30);
+	} else {
+		priv->rxdes0_edorr_mask = BIT(15);
+		priv->txdes0_edotr_mask = BIT(15);
+	}
+
+	return clk_get_bulk(dev, &priv->clks);
+}
+
+static int ftgmac100_probe(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct ftgmac100_data *priv = dev_get_priv(dev);
+	int ret;
+
+	priv->iobase = (struct ftgmac100 *)pdata->iobase;
+	priv->phy_mode = pdata->phy_interface;
+	priv->max_speed = pdata->max_speed;
+	priv->phy_addr = 0;
+
+	ret = clk_enable_bulk(&priv->clks);
+	if (ret)
+		goto out;
+
+	ret = ftgmac100_mdio_init(dev);
+	if (ret) {
+		dev_err(dev, "Failed to initialize mdiobus: %d\n", ret);
 		goto out;
 	}
 
-	/* Transmit and receive descriptors should align to 16 bytes */
-	priv = memalign(16, sizeof(struct ftgmac100_data));
-	if (!priv) {
-		printf("%s(): failed to allocate priv\n", __func__);
-		goto free_dev;
+	ret = ftgmac100_phy_init(dev);
+	if (ret) {
+		dev_err(dev, "Failed to initialize PHY: %d\n", ret);
+		goto out;
 	}
 
-	memset(dev, 0, sizeof(*dev));
-	memset(priv, 0, sizeof(*priv));
-
-	strcpy(dev->name, "FTGMAC100");
-	dev->iobase	= CONFIG_FTGMAC100_BASE;
-	dev->init	= ftgmac100_init;
-	dev->halt	= ftgmac100_halt;
-	dev->send	= ftgmac100_send;
-	dev->recv	= ftgmac100_recv;
-	dev->priv	= priv;
-
-	eth_register(dev);
-
-	ftgmac100_reset(dev);
-
-	return 1;
-
-free_dev:
-	free(dev);
 out:
+	if (ret)
+		clk_release_bulk(&priv->clks);
+
+	return ret;
+}
+
+static int ftgmac100_remove(struct udevice *dev)
+{
+	struct ftgmac100_data *priv = dev_get_priv(dev);
+
+	free(priv->phydev);
+	mdio_unregister(priv->bus);
+	mdio_free(priv->bus);
+	clk_release_bulk(&priv->clks);
+
 	return 0;
 }
+
+static const struct eth_ops ftgmac100_ops = {
+	.start	= ftgmac100_start,
+	.send	= ftgmac100_send,
+	.recv	= ftgmac100_recv,
+	.stop	= ftgmac100_stop,
+	.free_pkt = ftgmac100_free_pkt,
+	.write_hwaddr = ftgmac100_write_hwaddr,
+};
+
+static const struct udevice_id ftgmac100_ids[] = {
+	{ .compatible = "faraday,ftgmac100",  .data = FTGMAC100_MODEL_FARADAY },
+	{ .compatible = "aspeed,ast2500-mac", .data = FTGMAC100_MODEL_ASPEED  },
+	{ }
+};
+
+U_BOOT_DRIVER(ftgmac100) = {
+	.name	= "ftgmac100",
+	.id	= UCLASS_ETH,
+	.of_match = ftgmac100_ids,
+	.ofdata_to_platdata = ftgmac100_ofdata_to_platdata,
+	.probe	= ftgmac100_probe,
+	.remove = ftgmac100_remove,
+	.ops	= &ftgmac100_ops,
+	.priv_auto_alloc_size = sizeof(struct ftgmac100_data),
+	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
+	.flags	= DM_FLAG_ALLOC_PRIV_DMA,
+};
diff --git a/drivers/net/ftgmac100.h b/drivers/net/ftgmac100.h
index ffbe1f3..9a789e4 100644
--- a/drivers/net/ftgmac100.h
+++ b/drivers/net/ftgmac100.h
@@ -70,48 +70,48 @@
 /*
  * Interrupt status register & interrupt enable register
  */
-#define FTGMAC100_INT_RPKT_BUF		(1 << 0)
-#define FTGMAC100_INT_RPKT_FIFO		(1 << 1)
-#define FTGMAC100_INT_NO_RXBUF		(1 << 2)
-#define FTGMAC100_INT_RPKT_LOST		(1 << 3)
-#define FTGMAC100_INT_XPKT_ETH		(1 << 4)
-#define FTGMAC100_INT_XPKT_FIFO		(1 << 5)
-#define FTGMAC100_INT_NO_NPTXBUF	(1 << 6)
-#define FTGMAC100_INT_XPKT_LOST		(1 << 7)
-#define FTGMAC100_INT_AHB_ERR		(1 << 8)
-#define FTGMAC100_INT_PHYSTS_CHG	(1 << 9)
-#define FTGMAC100_INT_NO_HPTXBUF	(1 << 10)
+#define FTGMAC100_INT_RPKT_BUF		BIT(0)
+#define FTGMAC100_INT_RPKT_FIFO		BIT(1)
+#define FTGMAC100_INT_NO_RXBUF		BIT(2)
+#define FTGMAC100_INT_RPKT_LOST		BIT(3)
+#define FTGMAC100_INT_XPKT_ETH		BIT(4)
+#define FTGMAC100_INT_XPKT_FIFO		BIT(5)
+#define FTGMAC100_INT_NO_NPTXBUF	BIT(6)
+#define FTGMAC100_INT_XPKT_LOST		BIT(7)
+#define FTGMAC100_INT_AHB_ERR		BIT(8)
+#define FTGMAC100_INT_PHYSTS_CHG	BIT(9)
+#define FTGMAC100_INT_NO_HPTXBUF	BIT(10)
 
 /*
  * Interrupt timer control register
  */
 #define FTGMAC100_ITC_RXINT_CNT(x)	(((x) & 0xf) << 0)
 #define FTGMAC100_ITC_RXINT_THR(x)	(((x) & 0x7) << 4)
-#define FTGMAC100_ITC_RXINT_TIME_SEL	(1 << 7)
+#define FTGMAC100_ITC_RXINT_TIME_SEL	BIT(7)
 #define FTGMAC100_ITC_TXINT_CNT(x)	(((x) & 0xf) << 8)
 #define FTGMAC100_ITC_TXINT_THR(x)	(((x) & 0x7) << 12)
-#define FTGMAC100_ITC_TXINT_TIME_SEL	(1 << 15)
+#define FTGMAC100_ITC_TXINT_TIME_SEL	BIT(15)
 
 /*
  * Automatic polling timer control register
  */
 #define FTGMAC100_APTC_RXPOLL_CNT(x)	(((x) & 0xf) << 0)
-#define FTGMAC100_APTC_RXPOLL_TIME_SEL	(1 << 4)
+#define FTGMAC100_APTC_RXPOLL_TIME_SEL	BIT(4)
 #define FTGMAC100_APTC_TXPOLL_CNT(x)	(((x) & 0xf) << 8)
-#define FTGMAC100_APTC_TXPOLL_TIME_SEL	(1 << 12)
+#define FTGMAC100_APTC_TXPOLL_TIME_SEL	BIT(12)
 
 /*
  * DMA burst length and arbitration control register
  */
 #define FTGMAC100_DBLAC_RXFIFO_LTHR(x)	(((x) & 0x7) << 0)
 #define FTGMAC100_DBLAC_RXFIFO_HTHR(x)	(((x) & 0x7) << 3)
-#define FTGMAC100_DBLAC_RX_THR_EN	(1 << 6)
+#define FTGMAC100_DBLAC_RX_THR_EN	BIT(6)
 #define FTGMAC100_DBLAC_RXBURST_SIZE(x)	(((x) & 0x3) << 8)
 #define FTGMAC100_DBLAC_TXBURST_SIZE(x)	(((x) & 0x3) << 10)
 #define FTGMAC100_DBLAC_RXDES_SIZE(x)	(((x) & 0xf) << 12)
 #define FTGMAC100_DBLAC_TXDES_SIZE(x)	(((x) & 0xf) << 16)
 #define FTGMAC100_DBLAC_IFG_CNT(x)	(((x) & 0x7) << 20)
-#define FTGMAC100_DBLAC_IFG_INC		(1 << 23)
+#define FTGMAC100_DBLAC_IFG_INC		BIT(23)
 
 /*
  * DMA FIFO status register
@@ -122,12 +122,12 @@
 #define FTGMAC100_DMAFIFOS_TXDMA1_SM(dmafifos)	(((dmafifos) >> 12) & 0xf)
 #define FTGMAC100_DMAFIFOS_TXDMA2_SM(dmafifos)	(((dmafifos) >> 16) & 0x3)
 #define FTGMAC100_DMAFIFOS_TXDMA3_SM(dmafifos)	(((dmafifos) >> 18) & 0xf)
-#define FTGMAC100_DMAFIFOS_RXFIFO_EMPTY		(1 << 26)
-#define FTGMAC100_DMAFIFOS_TXFIFO_EMPTY		(1 << 27)
-#define FTGMAC100_DMAFIFOS_RXDMA_GRANT		(1 << 28)
-#define FTGMAC100_DMAFIFOS_TXDMA_GRANT		(1 << 29)
-#define FTGMAC100_DMAFIFOS_RXDMA_REQ		(1 << 30)
-#define FTGMAC100_DMAFIFOS_TXDMA_REQ		(1 << 31)
+#define FTGMAC100_DMAFIFOS_RXFIFO_EMPTY		BIT(26)
+#define FTGMAC100_DMAFIFOS_TXFIFO_EMPTY		BIT(27)
+#define FTGMAC100_DMAFIFOS_RXDMA_GRANT		BIT(28)
+#define FTGMAC100_DMAFIFOS_TXDMA_GRANT		BIT(29)
+#define FTGMAC100_DMAFIFOS_RXDMA_REQ		BIT(30)
+#define FTGMAC100_DMAFIFOS_TXDMA_REQ		BIT(31)
 
 /*
  * Receive buffer size register
@@ -137,26 +137,26 @@
 /*
  * MAC control register
  */
-#define FTGMAC100_MACCR_TXDMA_EN	(1 << 0)
-#define FTGMAC100_MACCR_RXDMA_EN	(1 << 1)
-#define FTGMAC100_MACCR_TXMAC_EN	(1 << 2)
-#define FTGMAC100_MACCR_RXMAC_EN	(1 << 3)
-#define FTGMAC100_MACCR_RM_VLAN		(1 << 4)
-#define FTGMAC100_MACCR_HPTXR_EN	(1 << 5)
-#define FTGMAC100_MACCR_LOOP_EN		(1 << 6)
-#define FTGMAC100_MACCR_ENRX_IN_HALFTX	(1 << 7)
-#define FTGMAC100_MACCR_FULLDUP		(1 << 8)
-#define FTGMAC100_MACCR_GIGA_MODE	(1 << 9)
-#define FTGMAC100_MACCR_CRC_APD		(1 << 10)
-#define FTGMAC100_MACCR_RX_RUNT		(1 << 12)
-#define FTGMAC100_MACCR_JUMBO_LF	(1 << 13)
-#define FTGMAC100_MACCR_RX_ALL		(1 << 14)
-#define FTGMAC100_MACCR_HT_MULTI_EN	(1 << 15)
-#define FTGMAC100_MACCR_RX_MULTIPKT	(1 << 16)
-#define FTGMAC100_MACCR_RX_BROADPKT	(1 << 17)
-#define FTGMAC100_MACCR_DISCARD_CRCERR	(1 << 18)
-#define FTGMAC100_MACCR_FAST_MODE	(1 << 19)
-#define FTGMAC100_MACCR_SW_RST		(1 << 31)
+#define FTGMAC100_MACCR_TXDMA_EN	BIT(0)
+#define FTGMAC100_MACCR_RXDMA_EN	BIT(1)
+#define FTGMAC100_MACCR_TXMAC_EN	BIT(2)
+#define FTGMAC100_MACCR_RXMAC_EN	BIT(3)
+#define FTGMAC100_MACCR_RM_VLAN		BIT(4)
+#define FTGMAC100_MACCR_HPTXR_EN	BIT(5)
+#define FTGMAC100_MACCR_LOOP_EN		BIT(6)
+#define FTGMAC100_MACCR_ENRX_IN_HALFTX	BIT(7)
+#define FTGMAC100_MACCR_FULLDUP		BIT(8)
+#define FTGMAC100_MACCR_GIGA_MODE	BIT(9)
+#define FTGMAC100_MACCR_CRC_APD		BIT(10)
+#define FTGMAC100_MACCR_RX_RUNT		BIT(12)
+#define FTGMAC100_MACCR_JUMBO_LF	BIT(13)
+#define FTGMAC100_MACCR_RX_ALL		BIT(14)
+#define FTGMAC100_MACCR_HT_MULTI_EN	BIT(15)
+#define FTGMAC100_MACCR_RX_MULTIPKT	BIT(16)
+#define FTGMAC100_MACCR_RX_BROADPKT	BIT(17)
+#define FTGMAC100_MACCR_DISCARD_CRCERR	BIT(18)
+#define FTGMAC100_MACCR_FAST_MODE	BIT(19)
+#define FTGMAC100_MACCR_SW_RST		BIT(31)
 
 /*
  * PHY control register
@@ -165,8 +165,8 @@
 #define FTGMAC100_PHYCR_MDC_CYCTHR(x)	((x) & 0x3f)
 #define FTGMAC100_PHYCR_PHYAD(x)	(((x) & 0x1f) << 16)
 #define FTGMAC100_PHYCR_REGAD(x)	(((x) & 0x1f) << 21)
-#define FTGMAC100_PHYCR_MIIRD		(1 << 26)
-#define FTGMAC100_PHYCR_MIIWR		(1 << 27)
+#define FTGMAC100_PHYCR_MIIRD		BIT(26)
+#define FTGMAC100_PHYCR_MIIWR		BIT(27)
 
 /*
  * PHY data register
@@ -182,23 +182,23 @@
 	unsigned int	txdes1;
 	unsigned int	txdes2;	/* not used by HW */
 	unsigned int	txdes3;	/* TXBUF_BADR */
-} __attribute__ ((aligned(16)));
+} __aligned(16);
 
 #define FTGMAC100_TXDES0_TXBUF_SIZE(x)	((x) & 0x3fff)
-#define FTGMAC100_TXDES0_EDOTR		(1 << 15)
-#define FTGMAC100_TXDES0_CRC_ERR	(1 << 19)
-#define FTGMAC100_TXDES0_LTS		(1 << 28)
-#define FTGMAC100_TXDES0_FTS		(1 << 29)
-#define FTGMAC100_TXDES0_TXDMA_OWN	(1 << 31)
+#define FTGMAC100_TXDES0_EDOTR		BIT(15)
+#define FTGMAC100_TXDES0_CRC_ERR	BIT(19)
+#define FTGMAC100_TXDES0_LTS		BIT(28)
+#define FTGMAC100_TXDES0_FTS		BIT(29)
+#define FTGMAC100_TXDES0_TXDMA_OWN	BIT(31)
 
 #define FTGMAC100_TXDES1_VLANTAG_CI(x)	((x) & 0xffff)
-#define FTGMAC100_TXDES1_INS_VLANTAG	(1 << 16)
-#define FTGMAC100_TXDES1_TCP_CHKSUM	(1 << 17)
-#define FTGMAC100_TXDES1_UDP_CHKSUM	(1 << 18)
-#define FTGMAC100_TXDES1_IP_CHKSUM	(1 << 19)
-#define FTGMAC100_TXDES1_LLC		(1 << 22)
-#define FTGMAC100_TXDES1_TX2FIC		(1 << 30)
-#define FTGMAC100_TXDES1_TXIC		(1 << 31)
+#define FTGMAC100_TXDES1_INS_VLANTAG	BIT(16)
+#define FTGMAC100_TXDES1_TCP_CHKSUM	BIT(17)
+#define FTGMAC100_TXDES1_UDP_CHKSUM	BIT(18)
+#define FTGMAC100_TXDES1_IP_CHKSUM	BIT(19)
+#define FTGMAC100_TXDES1_LLC		BIT(22)
+#define FTGMAC100_TXDES1_TX2FIC		BIT(30)
+#define FTGMAC100_TXDES1_TXIC		BIT(31)
 
 /*
  * Receive descriptor, aligned to 16 bytes
@@ -208,23 +208,23 @@
 	unsigned int	rxdes1;
 	unsigned int	rxdes2;	/* not used by HW */
 	unsigned int	rxdes3;	/* RXBUF_BADR */
-} __attribute__ ((aligned(16)));
+} __aligned(16);
 
 #define FTGMAC100_RXDES0_VDBC(x)	((x) & 0x3fff)
-#define FTGMAC100_RXDES0_EDORR		(1 << 15)
-#define FTGMAC100_RXDES0_MULTICAST	(1 << 16)
-#define FTGMAC100_RXDES0_BROADCAST	(1 << 17)
-#define FTGMAC100_RXDES0_RX_ERR		(1 << 18)
-#define FTGMAC100_RXDES0_CRC_ERR	(1 << 19)
-#define FTGMAC100_RXDES0_FTL		(1 << 20)
-#define FTGMAC100_RXDES0_RUNT		(1 << 21)
-#define FTGMAC100_RXDES0_RX_ODD_NB	(1 << 22)
-#define FTGMAC100_RXDES0_FIFO_FULL	(1 << 23)
-#define FTGMAC100_RXDES0_PAUSE_OPCODE	(1 << 24)
-#define FTGMAC100_RXDES0_PAUSE_FRAME	(1 << 25)
-#define FTGMAC100_RXDES0_LRS		(1 << 28)
-#define FTGMAC100_RXDES0_FRS		(1 << 29)
-#define FTGMAC100_RXDES0_RXPKT_RDY	(1 << 31)
+#define FTGMAC100_RXDES0_EDORR		BIT(15)
+#define FTGMAC100_RXDES0_MULTICAST	BIT(16)
+#define FTGMAC100_RXDES0_BROADCAST	BIT(17)
+#define FTGMAC100_RXDES0_RX_ERR		BIT(18)
+#define FTGMAC100_RXDES0_CRC_ERR	BIT(19)
+#define FTGMAC100_RXDES0_FTL		BIT(20)
+#define FTGMAC100_RXDES0_RUNT		BIT(21)
+#define FTGMAC100_RXDES0_RX_ODD_NB	BIT(22)
+#define FTGMAC100_RXDES0_FIFO_FULL	BIT(23)
+#define FTGMAC100_RXDES0_PAUSE_OPCODE	BIT(24)
+#define FTGMAC100_RXDES0_PAUSE_FRAME	BIT(25)
+#define FTGMAC100_RXDES0_LRS		BIT(28)
+#define FTGMAC100_RXDES0_FRS		BIT(29)
+#define FTGMAC100_RXDES0_RXPKT_RDY	BIT(31)
 
 #define FTGMAC100_RXDES1_VLANTAG_CI	0xffff
 #define FTGMAC100_RXDES1_PROT_MASK	(0x3 << 20)
@@ -232,11 +232,11 @@
 #define FTGMAC100_RXDES1_PROT_IP	(0x1 << 20)
 #define FTGMAC100_RXDES1_PROT_TCPIP	(0x2 << 20)
 #define FTGMAC100_RXDES1_PROT_UDPIP	(0x3 << 20)
-#define FTGMAC100_RXDES1_LLC		(1 << 22)
-#define FTGMAC100_RXDES1_DF		(1 << 23)
-#define FTGMAC100_RXDES1_VLANTAG_AVAIL	(1 << 24)
-#define FTGMAC100_RXDES1_TCP_CHKSUM_ERR	(1 << 25)
-#define FTGMAC100_RXDES1_UDP_CHKSUM_ERR	(1 << 26)
-#define FTGMAC100_RXDES1_IP_CHKSUM_ERR	(1 << 27)
+#define FTGMAC100_RXDES1_LLC		BIT(22)
+#define FTGMAC100_RXDES1_DF		BIT(23)
+#define FTGMAC100_RXDES1_VLANTAG_AVAIL	BIT(24)
+#define FTGMAC100_RXDES1_TCP_CHKSUM_ERR	BIT(25)
+#define FTGMAC100_RXDES1_UDP_CHKSUM_ERR	BIT(26)
+#define FTGMAC100_RXDES1_IP_CHKSUM_ERR	BIT(27)
 
 #endif /* __FTGMAC100_H */
diff --git a/drivers/net/mt7628-eth.c b/drivers/net/mt7628-eth.c
new file mode 100644
index 0000000..7833b2f
--- /dev/null
+++ b/drivers/net/mt7628-eth.c
@@ -0,0 +1,644 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * MediaTek ethernet IP driver for U-Boot
+ *
+ * Copyright (C) 2018 Stefan Roese <sr@denx.de>
+ *
+ * This code is mostly based on the code extracted from this MediaTek
+ * github repository:
+ *
+ * https://github.com/MediaTek-Labs/linkit-smart-uboot.git
+ *
+ * I was not able to find a specific license or other developers
+ * copyrights here, so I can't add them here.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <malloc.h>
+#include <miiphy.h>
+#include <net.h>
+#include <regmap.h>
+#include <syscon.h>
+#include <wait_bit.h>
+#include <asm/io.h>
+#include <linux/bitfield.h>
+#include <linux/err.h>
+
+/* System controller register */
+#define MT7628_RSTCTRL_REG	0x34
+#define RSTCTRL_EPHY_RST	BIT(24)
+
+#define MT7628_AGPIO_CFG_REG	0x3c
+#define MT7628_EPHY_GPIO_AIO_EN	GENMASK(20, 17)
+#define MT7628_EPHY_P0_DIS	BIT(16)
+
+#define MT7628_GPIO2_MODE_REG	0x64
+
+/* Ethernet frame engine register */
+#define PDMA_RELATED		0x0800
+
+#define TX_BASE_PTR0		(PDMA_RELATED + 0x000)
+#define TX_MAX_CNT0		(PDMA_RELATED + 0x004)
+#define TX_CTX_IDX0		(PDMA_RELATED + 0x008)
+#define TX_DTX_IDX0		(PDMA_RELATED + 0x00c)
+
+#define RX_BASE_PTR0		(PDMA_RELATED + 0x100)
+#define RX_MAX_CNT0		(PDMA_RELATED + 0x104)
+#define RX_CALC_IDX0		(PDMA_RELATED + 0x108)
+
+#define PDMA_GLO_CFG		(PDMA_RELATED + 0x204)
+#define PDMA_RST_IDX		(PDMA_RELATED + 0x208)
+#define DLY_INT_CFG		(PDMA_RELATED + 0x20c)
+
+#define SDM_RELATED		0x0c00
+
+#define SDM_MAC_ADRL		(SDM_RELATED + 0x0c)	/* MAC address LSB */
+#define SDM_MAC_ADRH		(SDM_RELATED + 0x10)	/* MAC Address MSB */
+
+#define RST_DTX_IDX0		BIT(0)
+#define RST_DRX_IDX0		BIT(16)
+
+#define TX_DMA_EN		BIT(0)
+#define TX_DMA_BUSY		BIT(1)
+#define RX_DMA_EN		BIT(2)
+#define RX_DMA_BUSY		BIT(3)
+#define TX_WB_DDONE		BIT(6)
+
+/* Ethernet switch register */
+#define MT7628_SWITCH_FCT0	0x0008
+#define MT7628_SWITCH_PFC1	0x0014
+#define MT7628_SWITCH_FPA	0x0084
+#define MT7628_SWITCH_SOCPC	0x008c
+#define MT7628_SWITCH_POC0	0x0090
+#define MT7628_SWITCH_POC2	0x0098
+#define MT7628_SWITCH_SGC	0x009c
+#define MT7628_SWITCH_PCR0	0x00c0
+#define PCR0_PHY_ADDR		GENMASK(4, 0)
+#define PCR0_PHY_REG		GENMASK(12, 8)
+#define PCR0_WT_PHY_CMD		BIT(13)
+#define PCR0_RD_PHY_CMD		BIT(14)
+#define PCR0_WT_DATA		GENMASK(31, 16)
+
+#define MT7628_SWITCH_PCR1	0x00c4
+#define PCR1_WT_DONE		BIT(0)
+#define PCR1_RD_RDY		BIT(1)
+#define PCR1_RD_DATA		GENMASK(31, 16)
+
+#define MT7628_SWITCH_FPA1	0x00c8
+#define MT7628_SWITCH_FCT2	0x00cc
+#define MT7628_SWITCH_SGC2	0x00e4
+#define MT7628_SWITCH_BMU_CTRL	0x0110
+
+/* rxd2 */
+#define RX_DMA_DONE		BIT(31)
+#define RX_DMA_LSO		BIT(30)
+#define RX_DMA_PLEN0		GENMASK(29, 16)
+#define RX_DMA_TAG		BIT(15)
+
+struct fe_rx_dma {
+	unsigned int rxd1;
+	unsigned int rxd2;
+	unsigned int rxd3;
+	unsigned int rxd4;
+} __packed __aligned(4);
+
+#define TX_DMA_PLEN0		GENMASK(29, 16)
+#define TX_DMA_LS1		BIT(14)
+#define TX_DMA_LS0		BIT(30)
+#define TX_DMA_DONE		BIT(31)
+
+#define TX_DMA_INS_VLAN_MT7621	BIT(16)
+#define TX_DMA_INS_VLAN		BIT(7)
+#define TX_DMA_INS_PPPOE	BIT(12)
+#define TX_DMA_PN		GENMASK(26, 24)
+
+struct fe_tx_dma {
+	unsigned int txd1;
+	unsigned int txd2;
+	unsigned int txd3;
+	unsigned int txd4;
+} __packed __aligned(4);
+
+#define NUM_RX_DESC		256
+#define NUM_TX_DESC		4
+
+#define PADDING_LENGTH		60
+
+#define MTK_QDMA_PAGE_SIZE	2048
+
+#define CONFIG_MDIO_TIMEOUT	100
+#define CONFIG_DMA_STOP_TIMEOUT	100
+#define CONFIG_TX_DMA_TIMEOUT	100
+
+#define LINK_DELAY_TIME		500		/* 500 ms */
+#define LINK_TIMEOUT		10000		/* 10 seconds */
+
+struct mt7628_eth_dev {
+	void __iomem *base;		/* frame engine base address */
+	void __iomem *eth_sw_base;	/* switch base address */
+	struct regmap *sysctrl_regmap;	/* system-controller reg-map */
+
+	struct mii_dev *bus;
+
+	struct fe_tx_dma *tx_ring;
+	struct fe_rx_dma *rx_ring;
+
+	u8 *rx_buf[NUM_RX_DESC];
+
+	/* Point to the next RXD DMA wants to use in RXD Ring0 */
+	int rx_dma_idx;
+	/* Point to the next TXD in TXD Ring0 CPU wants to use */
+	int tx_dma_idx;
+};
+
+static int mdio_wait_read(struct mt7628_eth_dev *priv, u32 mask, bool mask_set)
+{
+	void __iomem *base = priv->eth_sw_base;
+	int ret;
+
+	ret = wait_for_bit_le32(base + MT7628_SWITCH_PCR1, mask, mask_set,
+				CONFIG_MDIO_TIMEOUT, false);
+	if (ret) {
+		printf("MDIO operation timeout!\n");
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+static int mii_mgr_read(struct mt7628_eth_dev *priv,
+			u32 phy_addr, u32 phy_register, u32 *read_data)
+{
+	void __iomem *base = priv->eth_sw_base;
+	u32 status = 0;
+	u32 ret;
+
+	*read_data = 0xffff;
+	/* Make sure previous read operation is complete */
+	ret = mdio_wait_read(priv, PCR1_RD_RDY, false);
+	if (ret)
+		return ret;
+
+	writel(PCR0_RD_PHY_CMD |
+	       FIELD_PREP(PCR0_PHY_REG, phy_register) |
+	       FIELD_PREP(PCR0_PHY_ADDR, phy_addr),
+	       base + MT7628_SWITCH_PCR0);
+
+	/* Make sure previous read operation is complete */
+	ret = mdio_wait_read(priv, PCR1_RD_RDY, true);
+	if (ret)
+		return ret;
+
+	status = readl(base + MT7628_SWITCH_PCR1);
+	*read_data = FIELD_GET(PCR1_RD_DATA, status);
+
+	return 0;
+}
+
+static int mii_mgr_write(struct mt7628_eth_dev *priv,
+			 u32 phy_addr, u32 phy_register, u32 write_data)
+{
+	void __iomem *base = priv->eth_sw_base;
+	u32 data;
+	int ret;
+
+	/* Make sure previous write operation is complete */
+	ret = mdio_wait_read(priv, PCR1_WT_DONE, false);
+	if (ret)
+		return ret;
+
+	data = FIELD_PREP(PCR0_WT_DATA, write_data) |
+		FIELD_PREP(PCR0_PHY_REG, phy_register) |
+		FIELD_PREP(PCR0_PHY_ADDR, phy_addr) |
+		PCR0_WT_PHY_CMD;
+	writel(data, base + MT7628_SWITCH_PCR0);
+
+	return mdio_wait_read(priv, PCR1_WT_DONE, true);
+}
+
+static int mt7628_mdio_read(struct mii_dev *bus, int addr, int devad, int reg)
+{
+	u32 val;
+	int ret;
+
+	ret = mii_mgr_read(bus->priv, addr, reg, &val);
+	if (ret)
+		return ret;
+
+	return val;
+}
+
+static int mt7628_mdio_write(struct mii_dev *bus, int addr, int devad, int reg,
+			     u16 value)
+{
+	return mii_mgr_write(bus->priv, addr, reg, value);
+}
+
+static void mt7628_ephy_init(struct mt7628_eth_dev *priv)
+{
+	int i;
+
+	mii_mgr_write(priv, 0, 31, 0x2000);	/* change G2 page */
+	mii_mgr_write(priv, 0, 26, 0x0000);
+
+	for (i = 0; i < 5; i++) {
+		mii_mgr_write(priv, i, 31, 0x8000);	/* change L0 page */
+		mii_mgr_write(priv, i,  0, 0x3100);
+
+		/* EEE disable */
+		mii_mgr_write(priv, i, 30, 0xa000);
+		mii_mgr_write(priv, i, 31, 0xa000);	/* change L2 page */
+		mii_mgr_write(priv, i, 16, 0x0606);
+		mii_mgr_write(priv, i, 23, 0x0f0e);
+		mii_mgr_write(priv, i, 24, 0x1610);
+		mii_mgr_write(priv, i, 30, 0x1f15);
+		mii_mgr_write(priv, i, 28, 0x6111);
+	}
+
+	/* 100Base AOI setting */
+	mii_mgr_write(priv, 0, 31, 0x5000);	/* change G5 page */
+	mii_mgr_write(priv, 0, 19, 0x004a);
+	mii_mgr_write(priv, 0, 20, 0x015a);
+	mii_mgr_write(priv, 0, 21, 0x00ee);
+	mii_mgr_write(priv, 0, 22, 0x0033);
+	mii_mgr_write(priv, 0, 23, 0x020a);
+	mii_mgr_write(priv, 0, 24, 0x0000);
+	mii_mgr_write(priv, 0, 25, 0x024a);
+	mii_mgr_write(priv, 0, 26, 0x035a);
+	mii_mgr_write(priv, 0, 27, 0x02ee);
+	mii_mgr_write(priv, 0, 28, 0x0233);
+	mii_mgr_write(priv, 0, 29, 0x000a);
+	mii_mgr_write(priv, 0, 30, 0x0000);
+
+	/* Fix EPHY idle state abnormal behavior */
+	mii_mgr_write(priv, 0, 31, 0x4000);	/* change G4 page */
+	mii_mgr_write(priv, 0, 29, 0x000d);
+	mii_mgr_write(priv, 0, 30, 0x0500);
+}
+
+static void rt305x_esw_init(struct mt7628_eth_dev *priv)
+{
+	void __iomem *base = priv->eth_sw_base;
+
+	/*
+	 * FC_RLS_TH=200, FC_SET_TH=160
+	 * DROP_RLS=120, DROP_SET_TH=80
+	 */
+	writel(0xc8a07850, base + MT7628_SWITCH_FCT0);
+	writel(0x00000000, base + MT7628_SWITCH_SGC2);
+	writel(0x00405555, base + MT7628_SWITCH_PFC1);
+	writel(0x00007f7f, base + MT7628_SWITCH_POC0);
+	writel(0x00007f7f, base + MT7628_SWITCH_POC2);	/* disable VLAN */
+	writel(0x0002500c, base + MT7628_SWITCH_FCT2);
+	/* hashing algorithm=XOR48, aging interval=300sec */
+	writel(0x0008a301, base + MT7628_SWITCH_SGC);
+	writel(0x02404040, base + MT7628_SWITCH_SOCPC);
+
+	/* Ext PHY Addr=0x1f */
+	writel(0x3f502b28, base + MT7628_SWITCH_FPA1);
+	writel(0x00000000, base + MT7628_SWITCH_FPA);
+	/* 1us cycle number=125 (FE's clock=125Mhz) */
+	writel(0x7d000000, base + MT7628_SWITCH_BMU_CTRL);
+
+	/* Configure analog GPIO setup */
+	regmap_update_bits(priv->sysctrl_regmap, MT7628_AGPIO_CFG_REG,
+			   MT7628_EPHY_P0_DIS, MT7628_EPHY_GPIO_AIO_EN);
+
+	/* Reset PHY */
+	regmap_update_bits(priv->sysctrl_regmap, MT7628_RSTCTRL_REG,
+			   0, RSTCTRL_EPHY_RST);
+	regmap_update_bits(priv->sysctrl_regmap, MT7628_RSTCTRL_REG,
+			   RSTCTRL_EPHY_RST, 0);
+	mdelay(10);
+
+	/* Set P0 EPHY LED mode */
+	regmap_update_bits(priv->sysctrl_regmap, MT7628_GPIO2_MODE_REG,
+			   0x0ffc0ffc, 0x05540554);
+	mdelay(10);
+
+	mt7628_ephy_init(priv);
+}
+
+static void eth_dma_start(struct mt7628_eth_dev *priv)
+{
+	void __iomem *base = priv->base;
+
+	setbits_le32(base + PDMA_GLO_CFG, TX_WB_DDONE | RX_DMA_EN | TX_DMA_EN);
+}
+
+static void eth_dma_stop(struct mt7628_eth_dev *priv)
+{
+	void __iomem *base = priv->base;
+	int ret;
+
+	clrbits_le32(base + PDMA_GLO_CFG, TX_WB_DDONE | RX_DMA_EN | TX_DMA_EN);
+
+	/* Wait for DMA to stop */
+	ret = wait_for_bit_le32(base + PDMA_GLO_CFG,
+				RX_DMA_BUSY | TX_DMA_BUSY, false,
+				CONFIG_DMA_STOP_TIMEOUT, false);
+	if (ret)
+		printf("DMA stop timeout error!\n");
+}
+
+static int mt7628_eth_write_hwaddr(struct udevice *dev)
+{
+	struct mt7628_eth_dev *priv = dev_get_priv(dev);
+	void __iomem *base = priv->base;
+	u8 *addr = ((struct eth_pdata *)dev_get_platdata(dev))->enetaddr;
+	u32 val;
+
+	/* Set MAC address. */
+	val = addr[0];
+	val = (val << 8) | addr[1];
+	writel(val, base + SDM_MAC_ADRH);
+
+	val = addr[2];
+	val = (val << 8) | addr[3];
+	val = (val << 8) | addr[4];
+	val = (val << 8) | addr[5];
+	writel(val, base + SDM_MAC_ADRL);
+
+	return 0;
+}
+
+static int mt7628_eth_send(struct udevice *dev, void *packet, int length)
+{
+	struct mt7628_eth_dev *priv = dev_get_priv(dev);
+	void __iomem *base = priv->base;
+	int ret;
+	int idx;
+	int i;
+
+	idx = priv->tx_dma_idx;
+
+	/* Pad message to a minimum length */
+	if (length < PADDING_LENGTH) {
+		char *p = (char *)packet;
+
+		for (i = 0; i < PADDING_LENGTH - length; i++)
+			p[length + i] = 0;
+		length = PADDING_LENGTH;
+	}
+
+	/* Check if buffer is ready for next TX DMA */
+	ret = wait_for_bit_le32(&priv->tx_ring[idx].txd2, TX_DMA_DONE, true,
+				CONFIG_TX_DMA_TIMEOUT, false);
+	if (ret) {
+		printf("TX: DMA still busy on buffer %d\n", idx);
+		return ret;
+	}
+
+	flush_dcache_range((u32)packet, (u32)packet + length);
+
+	priv->tx_ring[idx].txd1 = CPHYSADDR(packet);
+	priv->tx_ring[idx].txd2 &= ~TX_DMA_PLEN0;
+	priv->tx_ring[idx].txd2 |= FIELD_PREP(TX_DMA_PLEN0, length);
+	priv->tx_ring[idx].txd2 &= ~TX_DMA_DONE;
+
+	idx = (idx + 1) % NUM_TX_DESC;
+
+	/* Make sure the writes executed at this place */
+	wmb();
+	writel(idx, base + TX_CTX_IDX0);
+
+	priv->tx_dma_idx = idx;
+
+	return 0;
+}
+
+static int mt7628_eth_recv(struct udevice *dev, int flags, uchar **packetp)
+{
+	struct mt7628_eth_dev *priv = dev_get_priv(dev);
+	u32 rxd_info;
+	int length;
+	int idx;
+
+	idx = priv->rx_dma_idx;
+
+	rxd_info = priv->rx_ring[idx].rxd2;
+	if ((rxd_info & RX_DMA_DONE) == 0)
+		return -EAGAIN;
+
+	length = FIELD_GET(RX_DMA_PLEN0, priv->rx_ring[idx].rxd2);
+	if (length == 0 || length > MTK_QDMA_PAGE_SIZE) {
+		printf("%s: invalid length (%d bytes)\n", __func__, length);
+		return -EIO;
+	}
+
+	*packetp = priv->rx_buf[idx];
+	invalidate_dcache_range((u32)*packetp, (u32)*packetp + length);
+
+	priv->rx_ring[idx].rxd4 = 0;
+	priv->rx_ring[idx].rxd2 = RX_DMA_LSO;
+
+	/* Make sure the writes executed at this place */
+	wmb();
+
+	return length;
+}
+
+static int mt7628_eth_free_pkt(struct udevice *dev, uchar *packet, int length)
+{
+	struct mt7628_eth_dev *priv = dev_get_priv(dev);
+	void __iomem *base = priv->base;
+	int idx;
+
+	idx = priv->rx_dma_idx;
+
+	/* Move point to next RXD which wants to alloc */
+	writel(idx, base + RX_CALC_IDX0);
+
+	/* Update to Next packet point that was received */
+	idx = (idx + 1) % NUM_RX_DESC;
+
+	priv->rx_dma_idx = idx;
+
+	return 0;
+}
+
+static int phy_link_up(struct mt7628_eth_dev *priv)
+{
+	u32 val;
+
+	mii_mgr_read(priv, 0x00, MII_BMSR, &val);
+	return !!(val & BMSR_LSTATUS);
+}
+
+static int mt7628_eth_start(struct udevice *dev)
+{
+	struct mt7628_eth_dev *priv = dev_get_priv(dev);
+	void __iomem *base = priv->base;
+	uchar packet[MTK_QDMA_PAGE_SIZE];
+	uchar *packetp;
+	int i;
+
+	for (i = 0; i < NUM_RX_DESC; i++) {
+		memset((void *)&priv->rx_ring[i], 0, sizeof(priv->rx_ring[0]));
+		priv->rx_ring[i].rxd2 |= RX_DMA_LSO;
+		priv->rx_ring[i].rxd1 = CPHYSADDR(priv->rx_buf[i]);
+	}
+
+	for (i = 0; i < NUM_TX_DESC; i++) {
+		memset((void *)&priv->tx_ring[i], 0, sizeof(priv->tx_ring[0]));
+		priv->tx_ring[i].txd2 = TX_DMA_LS0 | TX_DMA_DONE;
+		priv->tx_ring[i].txd4 = FIELD_PREP(TX_DMA_PN, 1);
+	}
+
+	priv->rx_dma_idx = 0;
+	priv->tx_dma_idx = 0;
+
+	/* Make sure the writes executed at this place */
+	wmb();
+
+	/* disable delay interrupt */
+	writel(0, base + DLY_INT_CFG);
+
+	clrbits_le32(base + PDMA_GLO_CFG, 0xffff0000);
+
+	/* Tell the adapter where the TX/RX rings are located. */
+	writel(CPHYSADDR(&priv->rx_ring[0]), base + RX_BASE_PTR0);
+	writel(CPHYSADDR((u32)&priv->tx_ring[0]), base + TX_BASE_PTR0);
+
+	writel(NUM_RX_DESC, base + RX_MAX_CNT0);
+	writel(NUM_TX_DESC, base + TX_MAX_CNT0);
+
+	writel(priv->tx_dma_idx, base + TX_CTX_IDX0);
+	writel(RST_DTX_IDX0, base + PDMA_RST_IDX);
+
+	writel(NUM_RX_DESC - 1, base + RX_CALC_IDX0);
+	writel(RST_DRX_IDX0, base + PDMA_RST_IDX);
+
+	/* Make sure the writes executed at this place */
+	wmb();
+	eth_dma_start(priv);
+
+	/* Check if link is not up yet */
+	if (!phy_link_up(priv)) {
+		/* Wait for link to come up */
+
+		printf("Waiting for link to come up .");
+		for (i = 0; i < (LINK_TIMEOUT / LINK_DELAY_TIME); i++) {
+			mdelay(LINK_DELAY_TIME);
+			if (phy_link_up(priv)) {
+				mdelay(100);	/* Ensure all is ready */
+				break;
+			}
+
+			printf(".");
+		}
+
+		if (phy_link_up(priv))
+			printf(" done\n");
+		else
+			printf(" timeout! Trying anyways\n");
+	}
+
+	/*
+	 * The integrated switch seems to queue some received ethernet
+	 * packets in some FIFO. Lets read the already queued packets
+	 * out by using the receive routine, so that these old messages
+	 * are dropped before the new xfer starts.
+	 */
+	packetp = &packet[0];
+	while (mt7628_eth_recv(dev, 0, &packetp) != -EAGAIN)
+		mt7628_eth_free_pkt(dev, packetp, 0);
+
+	return 0;
+}
+
+static void mt7628_eth_stop(struct udevice *dev)
+{
+	struct mt7628_eth_dev *priv = dev_get_priv(dev);
+
+	eth_dma_stop(priv);
+}
+
+static int mt7628_eth_probe(struct udevice *dev)
+{
+	struct mt7628_eth_dev *priv = dev_get_priv(dev);
+	struct udevice *syscon;
+	struct mii_dev *bus;
+	int ret;
+	int i;
+
+	/* Save frame-engine base address for later use */
+	priv->base = dev_remap_addr_index(dev, 0);
+	if (IS_ERR(priv->base))
+		return PTR_ERR(priv->base);
+
+	/* Save switch base address for later use */
+	priv->eth_sw_base = dev_remap_addr_index(dev, 1);
+	if (IS_ERR(priv->eth_sw_base))
+		return PTR_ERR(priv->eth_sw_base);
+
+	/* Get system controller regmap */
+	ret = uclass_get_device_by_phandle(UCLASS_SYSCON, dev,
+					   "syscon", &syscon);
+	if (ret) {
+		pr_err("unable to find syscon device\n");
+		return ret;
+	}
+
+	priv->sysctrl_regmap = syscon_get_regmap(syscon);
+	if (!priv->sysctrl_regmap) {
+		pr_err("unable to find regmap\n");
+		return -ENODEV;
+	}
+
+	/* Put rx and tx rings into KSEG1 area (uncached) */
+	priv->tx_ring = (struct fe_tx_dma *)
+		KSEG1ADDR(memalign(ARCH_DMA_MINALIGN,
+				   sizeof(*priv->tx_ring) * NUM_TX_DESC));
+	priv->rx_ring = (struct fe_rx_dma *)
+		KSEG1ADDR(memalign(ARCH_DMA_MINALIGN,
+				   sizeof(*priv->rx_ring) * NUM_RX_DESC));
+
+	for (i = 0; i < NUM_RX_DESC; i++)
+		priv->rx_buf[i] = memalign(PKTALIGN, MTK_QDMA_PAGE_SIZE);
+
+	bus = mdio_alloc();
+	if (!bus) {
+		printf("Failed to allocate MDIO bus\n");
+		return -ENOMEM;
+	}
+
+	bus->read = mt7628_mdio_read;
+	bus->write = mt7628_mdio_write;
+	snprintf(bus->name, sizeof(bus->name), dev->name);
+	bus->priv = (void *)priv;
+
+	ret = mdio_register(bus);
+	if (ret)
+		return ret;
+
+	/* Switch configuration */
+	rt305x_esw_init(priv);
+
+	return 0;
+}
+
+static const struct eth_ops mt7628_eth_ops = {
+	.start		= mt7628_eth_start,
+	.send		= mt7628_eth_send,
+	.recv		= mt7628_eth_recv,
+	.free_pkt	= mt7628_eth_free_pkt,
+	.stop		= mt7628_eth_stop,
+	.write_hwaddr	= mt7628_eth_write_hwaddr,
+};
+
+static const struct udevice_id mt7628_eth_ids[] = {
+	{ .compatible = "mediatek,mt7628-eth" },
+	{ }
+};
+
+U_BOOT_DRIVER(mt7628_eth) = {
+	.name	= "mt7628_eth",
+	.id	= UCLASS_ETH,
+	.of_match = mt7628_eth_ids,
+	.probe	= mt7628_eth_probe,
+	.ops	= &mt7628_eth_ops,
+	.priv_auto_alloc_size = sizeof(struct mt7628_eth_dev),
+	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
+};
diff --git a/drivers/net/phy/mscc.c b/drivers/net/phy/mscc.c
index 6f102f1..72bbda5 100644
--- a/drivers/net/phy/mscc.c
+++ b/drivers/net/phy/mscc.c
@@ -11,12 +11,16 @@
 
 #include <miiphy.h>
 #include <bitfield.h>
+#include <time.h>
+#include <linux/delay.h>
 
 /* Microsemi PHY ID's */
 #define PHY_ID_VSC8530                  0x00070560
 #define PHY_ID_VSC8531                  0x00070570
 #define PHY_ID_VSC8540                  0x00070760
 #define PHY_ID_VSC8541                  0x00070770
+#define PHY_ID_VSC8574			0x000704a0
+#define PHY_ID_VSC8584                  0x000707c0
 
 /* Microsemi VSC85xx PHY Register Pages */
 #define MSCC_EXT_PAGE_ACCESS            31     /* Page Access Register */
@@ -29,6 +33,17 @@
 #define MSCC_PHY_PAGE_TEST		0x2A30 /* TEST Page registers */
 #define MSCC_PHY_PAGE_TR		0x52B5 /* Token Ring Page registers */
 
+/* Std Page Register 18 */
+#define MSCC_PHY_BYPASS_CONTROL           18
+#define PARALLEL_DET_IGNORE_ADVERTISED    BIT(3)
+
+/* Std Page Register 22 */
+#define MSCC_PHY_EXT_CNTL_STATUS          22
+#define SMI_BROADCAST_WR_EN              BIT(0)
+
+/* Std Page Register 24 */
+#define MSCC_PHY_EXT_PHY_CNTL_2           24
+
 /* Std Page Register 28 - PHY AUX Control/Status */
 #define MIIM_AUX_CNTRL_STAT_REG		28
 #define MIIM_AUX_CNTRL_STAT_ACTIPHY_TO	(0x0004)
@@ -47,6 +62,37 @@
 #define MAC_IF_SELECTION_RGMII		(2)
 #define MAC_IF_SELECTION_POS		(11)
 #define MAC_IF_SELECTION_WIDTH		(2)
+#define VSC8584_MAC_IF_SELECTION_MASK     BIT(12)
+#define VSC8584_MAC_IF_SELECTION_SGMII    0
+#define VSC8584_MAC_IF_SELECTION_1000BASEX 1
+#define VSC8584_MAC_IF_SELECTION_POS      12
+#define MEDIA_OP_MODE_MASK		  GENMASK(10, 8)
+#define MEDIA_OP_MODE_COPPER		  0
+#define MEDIA_OP_MODE_SERDES		  1
+#define MEDIA_OP_MODE_1000BASEX		  2
+#define MEDIA_OP_MODE_100BASEFX		  3
+#define MEDIA_OP_MODE_AMS_COPPER_SERDES	  5
+#define MEDIA_OP_MODE_AMS_COPPER_1000BASEX	6
+#define MEDIA_OP_MODE_AMS_COPPER_100BASEFX	7
+#define MEDIA_OP_MODE_POS		  8
+
+/* Extended Page 1 Register 20E1 */
+#define MSCC_PHY_ACTIPHY_CNTL		  20
+#define PHY_ADDR_REVERSED		  BIT(9)
+
+/* Extended Page 1 Register 23E1 */
+
+#define MSCC_PHY_EXT_PHY_CNTL_4           23
+#define PHY_CNTL_4_ADDR_POS		  11
+
+/* Extended Page 1 Register 25E1 */
+#define MSCC_PHY_VERIPHY_CNTL_2		25
+
+/* Extended Page 1 Register 26E1 */
+#define MSCC_PHY_VERIPHY_CNTL_3		26
+
+/* Extended Page 2 Register 16E2 */
+#define MSCC_PHY_CU_PMD_TX_CNTL         16
 
 /* Extended Page 2 Register 20E2 */
 #define MSCC_PHY_RGMII_CNTL_REG		20
@@ -72,6 +118,85 @@
 #define RMII_CLK_OUT_ENABLE_WIDTH	(1)
 #define RMII_CLK_OUT_ENABLE_MASK	(0x10)
 
+/* Extended Page 3 Register 22E3 */
+#define MSCC_PHY_SERDES_TX_CRC_ERR_CNT	22
+
+/* Extended page GPIO register 00G */
+#define MSCC_DW8051_CNTL_STATUS		0
+#define MICRO_NSOFT_RESET		BIT(15)
+#define RUN_FROM_INT_ROM		BIT(14)
+#define AUTOINC_ADDR			BIT(13)
+#define PATCH_RAM_CLK			BIT(12)
+#define MICRO_PATCH_EN			BIT(7)
+#define DW8051_CLK_EN			BIT(4)
+#define MICRO_CLK_EN			BIT(3)
+#define MICRO_CLK_DIVIDE(x)		((x) >> 1)
+#define MSCC_DW8051_VLD_MASK		0xf1ff
+
+/* Extended page GPIO register 09G */
+#define MSCC_TRAP_ROM_ADDR(x)		((x) * 2 + 1)
+#define MSCC_TRAP_ROM_ADDR_SERDES_INIT	0x3eb7
+
+/* Extended page GPIO register 10G */
+#define MSCC_PATCH_RAM_ADDR(x)		(((x) + 1) * 2)
+#define MSCC_PATCH_RAM_ADDR_SERDES_INIT	0x4012
+
+/* Extended page GPIO register 11G */
+#define MSCC_INT_MEM_ADDR		11
+
+/* Extended page GPIO register 12G */
+#define MSCC_INT_MEM_CNTL		12
+#define READ_SFR			(BIT(14) | BIT(13))
+#define READ_PRAM			BIT(14)
+#define READ_ROM			BIT(13)
+#define READ_RAM			(0x00 << 13)
+#define INT_MEM_WRITE_EN		BIT(12)
+#define EN_PATCH_RAM_TRAP_ADDR(x)	BIT((x) + 7)
+#define INT_MEM_DATA_M			GENMASK(7, 0)
+#define INT_MEM_DATA(x)			(INT_MEM_DATA_M & (x))
+
+/* Extended page GPIO register 18G */
+#define MSCC_PHY_PROC_CMD		  18
+#define PROC_CMD_NCOMPLETED		  BIT(15)
+#define PROC_CMD_FAILED			  BIT(14)
+#define PROC_CMD_SGMII_PORT(x)		  ((x) << 8)
+#define PROC_CMD_FIBER_PORT(x)		  BIT(8 + (x) % 4)
+#define PROC_CMD_QSGMII_PORT		  (BIT(11) | BIT(10))
+#define PROC_CMD_RST_CONF_PORT		  BIT(7)
+#define PROC_CMD_RECONF_PORT		  (0 << 7)
+#define PROC_CMD_READ_MOD_WRITE_PORT	  BIT(6)
+#define PROC_CMD_WRITE			  BIT(6)
+#define PROC_CMD_READ			  (0 << 6)
+#define PROC_CMD_FIBER_DISABLE		  BIT(5)
+#define PROC_CMD_FIBER_100BASE_FX	  BIT(4)
+#define PROC_CMD_FIBER_1000BASE_X	  (0 << 4)
+#define PROC_CMD_SGMII_MAC		  (BIT(5) | BIT(4))
+#define PROC_CMD_QSGMII_MAC		  BIT(5)
+#define PROC_CMD_NO_MAC_CONF		  (0x00 << 4)
+#define PROC_CMD_1588_DEFAULT_INIT	  BIT(4)
+#define PROC_CMD_NOP			  GENMASK(3, 0)
+#define PROC_CMD_PHY_INIT		  (BIT(3) | BIT(1))
+#define PROC_CMD_CRC16			  BIT(3)
+#define PROC_CMD_FIBER_MEDIA_CONF	  BIT(0)
+#define PROC_CMD_MCB_ACCESS_MAC_CONF	  (0x0000 << 0)
+#define PROC_CMD_NCOMPLETED_TIMEOUT_MS    500
+
+/* Extended page GPIO register 19G */
+#define MSCC_PHY_MAC_CFG_FASTLINK	  19
+#define MAC_CFG_MASK			  GENMASK(15, 14)
+#define MAC_CFG_SGMII			  (0x00 << 14)
+#define MAC_CFG_QSGMII			  BIT(14)
+
+/* Test Registers */
+#define MSCC_PHY_TEST_PAGE_5		5
+
+#define MSCC_PHY_TEST_PAGE_8		8
+#define TR_CLK_DISABLE			BIT(15)
+
+#define MSCC_PHY_TEST_PAGE_9		9
+#define MSCC_PHY_TEST_PAGE_20		20
+#define MSCC_PHY_TEST_PAGE_24		24
+
 /* Token Ring Page 0x52B5 Registers */
 #define MSCC_PHY_REG_TR_ADDR_16		16
 #define MSCC_PHY_REG_TR_DATA_17		17
@@ -110,6 +235,15 @@
 #define MSCC_PHY_RESET_TIMEOUT		(100)
 #define MSCC_PHY_MICRO_TIMEOUT		(500)
 
+#define VSC8584_REVB		0x0001
+#define MSCC_DEV_REV_MASK	GENMASK(3, 0)
+
+#define MSCC_VSC8574_REVB_INT8051_FW_START_ADDR 0x4000
+#define MSCC_VSC8574_REVB_INT8051_FW_CRC	0x29e8
+
+#define MSCC_VSC8584_REVB_INT8051_FW_START_ADDR	0xe800
+#define MSCC_VSC8584_REVB_INT8051_FW_CRC	0xfb48
+
 /* RGMII/GMII Clock Delay (Skew) Options */ enum vsc_phy_rgmii_skew {
 	VSC_PHY_RGMII_DELAY_200_PS,
 	VSC_PHY_RGMII_DELAY_800_PS,
@@ -133,6 +267,743 @@
 	VSC_PHY_CLK_SLEW_RATE_7,
 };
 
+struct vsc85xx_priv {
+	int (*config_pre)(struct phy_device *phydev);
+};
+
+static void vsc8584_csr_write(struct mii_dev *bus, int phy0, u16 addr, u32 val)
+{
+	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18,
+		   val >> 16);
+	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17,
+		   val & GENMASK(15, 0));
+	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
+		   MSCC_PHY_TR_16_WRITE | addr);
+}
+
+static int vsc8584_cmd(struct mii_dev *bus, int phy, u16 val)
+{
+	unsigned long deadline;
+	u16 reg_val;
+
+	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+		   MSCC_PHY_PAGE_GPIO);
+
+	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_PROC_CMD,
+		   PROC_CMD_NCOMPLETED | val);
+
+	deadline = timer_get_us() + PROC_CMD_NCOMPLETED_TIMEOUT_MS * 1000;
+	do {
+		reg_val = bus->read(bus, phy, MDIO_DEVAD_NONE,
+				    MSCC_PHY_PROC_CMD);
+	} while (timer_get_us() <= deadline &&
+		 (reg_val & PROC_CMD_NCOMPLETED) &&
+		 !(reg_val & PROC_CMD_FAILED));
+
+	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+		   MSCC_PHY_PAGE_STD);
+
+	if (reg_val & PROC_CMD_FAILED)
+		return -EIO;
+	if (reg_val & PROC_CMD_NCOMPLETED)
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+static int vsc8584_micro_deassert_reset(struct mii_dev *bus, int phy,
+					bool patch_en)
+{
+	u32 enable, release;
+
+	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+		   MSCC_PHY_PAGE_GPIO);
+
+	enable = RUN_FROM_INT_ROM | MICRO_CLK_EN | DW8051_CLK_EN;
+	release = MICRO_NSOFT_RESET | RUN_FROM_INT_ROM | DW8051_CLK_EN |
+		MICRO_CLK_EN;
+
+	if (patch_en) {
+		enable |= MICRO_PATCH_EN;
+		release |= MICRO_PATCH_EN;
+
+		/* Clear all patches */
+		bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL,
+			   READ_RAM);
+	}
+
+	/*
+	 * Enable 8051 Micro clock; CLEAR/SET patch present; disable PRAM clock
+	 * override and addr. auto-incr; operate at 125 MHz
+	 */
+	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS, enable);
+	/* Release 8051 Micro SW reset */
+	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS, release);
+
+	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+		   MSCC_PHY_PAGE_STD);
+
+	return 0;
+}
+
+static int vsc8584_micro_assert_reset(struct mii_dev *bus, int phy)
+{
+	int ret;
+	u16 reg;
+
+	ret = vsc8584_cmd(bus, phy, PROC_CMD_NOP);
+	if (ret)
+		return ret;
+
+	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+		   MSCC_PHY_PAGE_GPIO);
+
+	reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL);
+	reg &= ~EN_PATCH_RAM_TRAP_ADDR(4);
+	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, reg);
+
+	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_TRAP_ROM_ADDR(4), 0x005b);
+	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PATCH_RAM_ADDR(4), 0x005b);
+
+	reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL);
+	reg |= EN_PATCH_RAM_TRAP_ADDR(4);
+	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, reg);
+
+	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_PROC_CMD, PROC_CMD_NOP);
+
+	reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS);
+	reg &= ~MICRO_NSOFT_RESET;
+	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS, reg);
+
+	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_PROC_CMD,
+		   PROC_CMD_MCB_ACCESS_MAC_CONF | PROC_CMD_SGMII_PORT(0) |
+		   PROC_CMD_NO_MAC_CONF | PROC_CMD_READ);
+
+	reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL);
+	reg &= ~EN_PATCH_RAM_TRAP_ADDR(4);
+	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, reg);
+
+	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+		   MSCC_PHY_PAGE_STD);
+
+	return 0;
+}
+
+static const u8 fw_patch_vsc8574[] = {
+	0x46, 0x4a, 0x02, 0x43, 0x37, 0x02, 0x46, 0x26, 0x02, 0x46, 0x77, 0x02,
+	0x45, 0x60, 0x02, 0x45, 0xaf, 0xed, 0xff, 0xe5, 0xfc, 0x54, 0x38, 0x64,
+	0x20, 0x70, 0x08, 0x65, 0xff, 0x70, 0x04, 0xed, 0x44, 0x80, 0xff, 0x22,
+	0x8f, 0x19, 0x7b, 0xbb, 0x7d, 0x0e, 0x7f, 0x04, 0x12, 0x3d, 0xd7, 0xef,
+	0x4e, 0x60, 0x03, 0x02, 0x41, 0xf9, 0xe4, 0xf5, 0x1a, 0x74, 0x01, 0x7e,
+	0x00, 0xa8, 0x1a, 0x08, 0x80, 0x05, 0xc3, 0x33, 0xce, 0x33, 0xce, 0xd8,
+	0xf9, 0xff, 0xef, 0x55, 0x19, 0x70, 0x03, 0x02, 0x41, 0xed, 0x85, 0x1a,
+	0xfb, 0x7b, 0xbb, 0xe4, 0xfd, 0xff, 0x12, 0x3d, 0xd7, 0xef, 0x4e, 0x60,
+	0x03, 0x02, 0x41, 0xed, 0xe5, 0x1a, 0x54, 0x02, 0x75, 0x1d, 0x00, 0x25,
+	0xe0, 0x25, 0xe0, 0xf5, 0x1c, 0xe4, 0x78, 0xc5, 0xf6, 0xd2, 0x0a, 0x12,
+	0x41, 0xfa, 0x7b, 0xff, 0x7d, 0x12, 0x7f, 0x07, 0x12, 0x3d, 0xd7, 0xef,
+	0x4e, 0x60, 0x03, 0x02, 0x41, 0xe7, 0xc2, 0x0a, 0x74, 0xc7, 0x25, 0x1a,
+	0xf9, 0x74, 0xe7, 0x25, 0x1a, 0xf8, 0xe6, 0x27, 0xf5, 0x1b, 0xe5, 0x1d,
+	0x24, 0x5b, 0x12, 0x45, 0xea, 0x12, 0x3e, 0xda, 0x7b, 0xfc, 0x7d, 0x11,
+	0x7f, 0x07, 0x12, 0x3d, 0xd7, 0x78, 0xcc, 0xef, 0xf6, 0x78, 0xc1, 0xe6,
+	0xfe, 0xef, 0xd3, 0x9e, 0x40, 0x06, 0x78, 0xcc, 0xe6, 0x78, 0xc1, 0xf6,
+	0x12, 0x41, 0xfa, 0x7b, 0xec, 0x7d, 0x12, 0x7f, 0x07, 0x12, 0x3d, 0xd7,
+	0x78, 0xcb, 0xef, 0xf6, 0xbf, 0x07, 0x06, 0x78, 0xc3, 0x76, 0x1a, 0x80,
+	0x1f, 0x78, 0xc5, 0xe6, 0xff, 0x60, 0x0f, 0xc3, 0xe5, 0x1b, 0x9f, 0xff,
+	0x78, 0xcb, 0xe6, 0x85, 0x1b, 0xf0, 0xa4, 0x2f, 0x80, 0x07, 0x78, 0xcb,
+	0xe6, 0x85, 0x1b, 0xf0, 0xa4, 0x78, 0xc3, 0xf6, 0xe4, 0x78, 0xc2, 0xf6,
+	0x78, 0xc2, 0xe6, 0xff, 0xc3, 0x08, 0x96, 0x40, 0x03, 0x02, 0x41, 0xd1,
+	0xef, 0x54, 0x03, 0x60, 0x33, 0x14, 0x60, 0x46, 0x24, 0xfe, 0x60, 0x42,
+	0x04, 0x70, 0x4b, 0xef, 0x24, 0x02, 0xff, 0xe4, 0x33, 0xfe, 0xef, 0x78,
+	0x02, 0xce, 0xa2, 0xe7, 0x13, 0xce, 0x13, 0xd8, 0xf8, 0xff, 0xe5, 0x1d,
+	0x24, 0x5c, 0xcd, 0xe5, 0x1c, 0x34, 0xf0, 0xcd, 0x2f, 0xff, 0xed, 0x3e,
+	0xfe, 0x12, 0x46, 0x0d, 0x7d, 0x11, 0x80, 0x0b, 0x78, 0xc2, 0xe6, 0x70,
+	0x04, 0x7d, 0x11, 0x80, 0x02, 0x7d, 0x12, 0x7f, 0x07, 0x12, 0x3e, 0x9a,
+	0x8e, 0x1e, 0x8f, 0x1f, 0x80, 0x03, 0xe5, 0x1e, 0xff, 0x78, 0xc5, 0xe6,
+	0x06, 0x24, 0xcd, 0xf8, 0xa6, 0x07, 0x78, 0xc2, 0x06, 0xe6, 0xb4, 0x1a,
+	0x0a, 0xe5, 0x1d, 0x24, 0x5c, 0x12, 0x45, 0xea, 0x12, 0x3e, 0xda, 0x78,
+	0xc5, 0xe6, 0x65, 0x1b, 0x70, 0x82, 0x75, 0xdb, 0x20, 0x75, 0xdb, 0x28,
+	0x12, 0x46, 0x02, 0x12, 0x46, 0x02, 0xe5, 0x1a, 0x12, 0x45, 0xf5, 0xe5,
+	0x1a, 0xc3, 0x13, 0x12, 0x45, 0xf5, 0x78, 0xc5, 0x16, 0xe6, 0x24, 0xcd,
+	0xf8, 0xe6, 0xff, 0x7e, 0x08, 0x1e, 0xef, 0xa8, 0x06, 0x08, 0x80, 0x02,
+	0xc3, 0x13, 0xd8, 0xfc, 0xfd, 0xc4, 0x33, 0x54, 0xe0, 0xf5, 0xdb, 0xef,
+	0xa8, 0x06, 0x08, 0x80, 0x02, 0xc3, 0x13, 0xd8, 0xfc, 0xfd, 0xc4, 0x33,
+	0x54, 0xe0, 0x44, 0x08, 0xf5, 0xdb, 0xee, 0x70, 0xd8, 0x78, 0xc5, 0xe6,
+	0x70, 0xc8, 0x75, 0xdb, 0x10, 0x02, 0x40, 0xfd, 0x78, 0xc2, 0xe6, 0xc3,
+	0x94, 0x17, 0x50, 0x0e, 0xe5, 0x1d, 0x24, 0x62, 0x12, 0x42, 0x08, 0xe5,
+	0x1d, 0x24, 0x5c, 0x12, 0x42, 0x08, 0x20, 0x0a, 0x03, 0x02, 0x40, 0x76,
+	0x05, 0x1a, 0xe5, 0x1a, 0xc3, 0x94, 0x04, 0x50, 0x03, 0x02, 0x40, 0x3a,
+	0x22, 0xe5, 0x1d, 0x24, 0x5c, 0xff, 0xe5, 0x1c, 0x34, 0xf0, 0xfe, 0x12,
+	0x46, 0x0d, 0x22, 0xff, 0xe5, 0x1c, 0x34, 0xf0, 0xfe, 0x12, 0x46, 0x0d,
+	0x22, 0xe4, 0xf5, 0x19, 0x12, 0x46, 0x43, 0x20, 0xe7, 0x1e, 0x7b, 0xfe,
+	0x12, 0x42, 0xf9, 0xef, 0xc4, 0x33, 0x33, 0x54, 0xc0, 0xff, 0xc0, 0x07,
+	0x7b, 0x54, 0x12, 0x42, 0xf9, 0xd0, 0xe0, 0x4f, 0xff, 0x74, 0x2a, 0x25,
+	0x19, 0xf8, 0xa6, 0x07, 0x12, 0x46, 0x43, 0x20, 0xe7, 0x03, 0x02, 0x42,
+	0xdf, 0x54, 0x03, 0x64, 0x03, 0x70, 0x03, 0x02, 0x42, 0xcf, 0x7b, 0xcb,
+	0x12, 0x43, 0x2c, 0x8f, 0xfb, 0x7b, 0x30, 0x7d, 0x03, 0xe4, 0xff, 0x12,
+	0x3d, 0xd7, 0xc3, 0xef, 0x94, 0x02, 0xee, 0x94, 0x00, 0x50, 0x2a, 0x12,
+	0x42, 0xec, 0xef, 0x4e, 0x70, 0x23, 0x12, 0x43, 0x04, 0x60, 0x0a, 0x12,
+	0x43, 0x12, 0x70, 0x0c, 0x12, 0x43, 0x1f, 0x70, 0x07, 0x12, 0x46, 0x39,
+	0x7b, 0x03, 0x80, 0x07, 0x12, 0x46, 0x39, 0x12, 0x46, 0x43, 0xfb, 0x7a,
+	0x00, 0x7d, 0x54, 0x80, 0x3e, 0x12, 0x42, 0xec, 0xef, 0x4e, 0x70, 0x24,
+	0x12, 0x43, 0x04, 0x60, 0x0a, 0x12, 0x43, 0x12, 0x70, 0x0f, 0x12, 0x43,
+	0x1f, 0x70, 0x0a, 0x12, 0x46, 0x39, 0xe4, 0xfb, 0xfa, 0x7d, 0xee, 0x80,
+	0x1e, 0x12, 0x46, 0x39, 0x7b, 0x01, 0x7a, 0x00, 0x7d, 0xee, 0x80, 0x13,
+	0x12, 0x46, 0x39, 0x12, 0x46, 0x43, 0x54, 0x40, 0xfe, 0xc4, 0x13, 0x13,
+	0x54, 0x03, 0xfb, 0x7a, 0x00, 0x7d, 0xee, 0x12, 0x38, 0xbd, 0x7b, 0xff,
+	0x12, 0x43, 0x2c, 0xef, 0x4e, 0x70, 0x07, 0x74, 0x2a, 0x25, 0x19, 0xf8,
+	0xe4, 0xf6, 0x05, 0x19, 0xe5, 0x19, 0xc3, 0x94, 0x02, 0x50, 0x03, 0x02,
+	0x42, 0x15, 0x22, 0xe5, 0x19, 0x24, 0x17, 0xfd, 0x7b, 0x20, 0x7f, 0x04,
+	0x12, 0x3d, 0xd7, 0x22, 0xe5, 0x19, 0x24, 0x17, 0xfd, 0x7f, 0x04, 0x12,
+	0x3d, 0xd7, 0x22, 0x7b, 0x22, 0x7d, 0x18, 0x7f, 0x06, 0x12, 0x3d, 0xd7,
+	0xef, 0x64, 0x01, 0x4e, 0x22, 0x7d, 0x1c, 0xe4, 0xff, 0x12, 0x3e, 0x9a,
+	0xef, 0x54, 0x1b, 0x64, 0x0a, 0x22, 0x7b, 0xcc, 0x7d, 0x10, 0xff, 0x12,
+	0x3d, 0xd7, 0xef, 0x64, 0x01, 0x4e, 0x22, 0xe5, 0x19, 0x24, 0x17, 0xfd,
+	0x7f, 0x04, 0x12, 0x3d, 0xd7, 0x22, 0xd2, 0x08, 0x75, 0xfb, 0x03, 0xab,
+	0x7e, 0xaa, 0x7d, 0x7d, 0x19, 0x7f, 0x03, 0x12, 0x3e, 0xda, 0xe5, 0x7e,
+	0x54, 0x0f, 0x24, 0xf3, 0x60, 0x03, 0x02, 0x43, 0xe9, 0x12, 0x46, 0x5a,
+	0x12, 0x46, 0x61, 0xd8, 0xfb, 0xff, 0x20, 0xe2, 0x35, 0x13, 0x92, 0x0c,
+	0xef, 0xa2, 0xe1, 0x92, 0x0b, 0x30, 0x0c, 0x2a, 0xe4, 0xf5, 0x10, 0x7b,
+	0xfe, 0x12, 0x43, 0xff, 0xef, 0xc4, 0x33, 0x33, 0x54, 0xc0, 0xff, 0xc0,
+	0x07, 0x7b, 0x54, 0x12, 0x43, 0xff, 0xd0, 0xe0, 0x4f, 0xff, 0x74, 0x2a,
+	0x25, 0x10, 0xf8, 0xa6, 0x07, 0x05, 0x10, 0xe5, 0x10, 0xc3, 0x94, 0x02,
+	0x40, 0xd9, 0x12, 0x46, 0x5a, 0x12, 0x46, 0x61, 0xd8, 0xfb, 0x54, 0x05,
+	0x64, 0x04, 0x70, 0x27, 0x78, 0xc4, 0xe6, 0x78, 0xc6, 0xf6, 0xe5, 0x7d,
+	0xff, 0x33, 0x95, 0xe0, 0xef, 0x54, 0x0f, 0x78, 0xc4, 0xf6, 0x12, 0x44,
+	0x0a, 0x20, 0x0c, 0x0c, 0x12, 0x46, 0x5a, 0x12, 0x46, 0x61, 0xd8, 0xfb,
+	0x13, 0x92, 0x0d, 0x22, 0xc2, 0x0d, 0x22, 0x12, 0x46, 0x5a, 0x12, 0x46,
+	0x61, 0xd8, 0xfb, 0x54, 0x05, 0x64, 0x05, 0x70, 0x1e, 0x78, 0xc4, 0x7d,
+	0xb8, 0x12, 0x43, 0xf5, 0x78, 0xc1, 0x7d, 0x74, 0x12, 0x43, 0xf5, 0xe4,
+	0x78, 0xc1, 0xf6, 0x22, 0x7b, 0x01, 0x7a, 0x00, 0x7d, 0xee, 0x7f, 0x92,
+	0x12, 0x38, 0xbd, 0x22, 0xe6, 0xfb, 0x7a, 0x00, 0x7f, 0x92, 0x12, 0x38,
+	0xbd, 0x22, 0xe5, 0x10, 0x24, 0x17, 0xfd, 0x7f, 0x04, 0x12, 0x3d, 0xd7,
+	0x22, 0x78, 0xc1, 0xe6, 0xfb, 0x7a, 0x00, 0x7d, 0x74, 0x7f, 0x92, 0x12,
+	0x38, 0xbd, 0xe4, 0x78, 0xc1, 0xf6, 0xf5, 0x11, 0x74, 0x01, 0x7e, 0x00,
+	0xa8, 0x11, 0x08, 0x80, 0x05, 0xc3, 0x33, 0xce, 0x33, 0xce, 0xd8, 0xf9,
+	0xff, 0x78, 0xc4, 0xe6, 0xfd, 0xef, 0x5d, 0x60, 0x44, 0x85, 0x11, 0xfb,
+	0xe5, 0x11, 0x54, 0x02, 0x25, 0xe0, 0x25, 0xe0, 0xfe, 0xe4, 0x24, 0x5b,
+	0xfb, 0xee, 0x12, 0x45, 0xed, 0x12, 0x3e, 0xda, 0x7b, 0x40, 0x7d, 0x11,
+	0x7f, 0x07, 0x12, 0x3d, 0xd7, 0x74, 0xc7, 0x25, 0x11, 0xf8, 0xa6, 0x07,
+	0x7b, 0x11, 0x7d, 0x12, 0x7f, 0x07, 0x12, 0x3d, 0xd7, 0xef, 0x4e, 0x60,
+	0x09, 0x74, 0xe7, 0x25, 0x11, 0xf8, 0x76, 0x04, 0x80, 0x07, 0x74, 0xe7,
+	0x25, 0x11, 0xf8, 0x76, 0x0a, 0x05, 0x11, 0xe5, 0x11, 0xc3, 0x94, 0x04,
+	0x40, 0x9a, 0x78, 0xc6, 0xe6, 0x70, 0x15, 0x78, 0xc4, 0xe6, 0x60, 0x10,
+	0x75, 0xd9, 0x38, 0x75, 0xdb, 0x10, 0x7d, 0xfe, 0x12, 0x44, 0xb8, 0x7d,
+	0x76, 0x12, 0x44, 0xb8, 0x79, 0xc6, 0xe7, 0x78, 0xc4, 0x66, 0xff, 0x60,
+	0x03, 0x12, 0x40, 0x25, 0x78, 0xc4, 0xe6, 0x70, 0x09, 0xfb, 0xfa, 0x7d,
+	0xfe, 0x7f, 0x8e, 0x12, 0x38, 0xbd, 0x22, 0x7b, 0x01, 0x7a, 0x00, 0x7f,
+	0x8e, 0x12, 0x38, 0xbd, 0x22, 0xe4, 0xf5, 0xfb, 0x7d, 0x1c, 0xe4, 0xff,
+	0x12, 0x3e, 0x9a, 0xad, 0x07, 0xac, 0x06, 0xec, 0x54, 0xc0, 0xff, 0xed,
+	0x54, 0x3f, 0x4f, 0xf5, 0x20, 0x30, 0x06, 0x2c, 0x30, 0x01, 0x08, 0xa2,
+	0x04, 0x72, 0x03, 0x92, 0x07, 0x80, 0x21, 0x30, 0x04, 0x06, 0x7b, 0xcc,
+	0x7d, 0x11, 0x80, 0x0d, 0x30, 0x03, 0x06, 0x7b, 0xcc, 0x7d, 0x10, 0x80,
+	0x04, 0x7b, 0x66, 0x7d, 0x16, 0xe4, 0xff, 0x12, 0x3d, 0xd7, 0xee, 0x4f,
+	0x24, 0xff, 0x92, 0x07, 0xaf, 0xfb, 0x74, 0x26, 0x2f, 0xf8, 0xe6, 0xff,
+	0xa6, 0x20, 0x20, 0x07, 0x39, 0x8f, 0x20, 0x30, 0x07, 0x34, 0x30, 0x00,
+	0x31, 0x20, 0x04, 0x2e, 0x20, 0x03, 0x2b, 0xe4, 0xf5, 0xff, 0x75, 0xfc,
+	0xc2, 0xe5, 0xfc, 0x30, 0xe0, 0xfb, 0xaf, 0xfe, 0xef, 0x20, 0xe3, 0x1a,
+	0xae, 0xfd, 0x44, 0x08, 0xf5, 0xfe, 0x75, 0xfc, 0x80, 0xe5, 0xfc, 0x30,
+	0xe0, 0xfb, 0x8f, 0xfe, 0x8e, 0xfd, 0x75, 0xfc, 0x80, 0xe5, 0xfc, 0x30,
+	0xe0, 0xfb, 0x05, 0xfb, 0xaf, 0xfb, 0xef, 0xc3, 0x94, 0x04, 0x50, 0x03,
+	0x02, 0x44, 0xc5, 0xe4, 0xf5, 0xfb, 0x22, 0xe5, 0x7e, 0x54, 0x0f, 0x64,
+	0x01, 0x70, 0x23, 0xe5, 0x7e, 0x30, 0xe4, 0x1e, 0x90, 0x47, 0xd0, 0xe0,
+	0x44, 0x02, 0xf0, 0x54, 0xfb, 0xf0, 0x90, 0x47, 0xd4, 0xe0, 0x44, 0x04,
+	0xf0, 0x7b, 0x03, 0x7d, 0x5b, 0x7f, 0x5d, 0x12, 0x36, 0x29, 0x7b, 0x0e,
+	0x80, 0x1c, 0x90, 0x47, 0xd0, 0xe0, 0x54, 0xfd, 0xf0, 0x44, 0x04, 0xf0,
+	0x90, 0x47, 0xd4, 0xe0, 0x54, 0xfb, 0xf0, 0x7b, 0x02, 0x7d, 0x5b, 0x7f,
+	0x5d, 0x12, 0x36, 0x29, 0x7b, 0x06, 0x7d, 0x60, 0x7f, 0x63, 0x12, 0x36,
+	0x29, 0x22, 0xe5, 0x7e, 0x30, 0xe5, 0x35, 0x30, 0xe4, 0x0b, 0x7b, 0x02,
+	0x7d, 0x33, 0x7f, 0x35, 0x12, 0x36, 0x29, 0x80, 0x10, 0x7b, 0x01, 0x7d,
+	0x33, 0x7f, 0x35, 0x12, 0x36, 0x29, 0x90, 0x47, 0xd2, 0xe0, 0x44, 0x04,
+	0xf0, 0x90, 0x47, 0xd2, 0xe0, 0x54, 0xf7, 0xf0, 0x90, 0x47, 0xd1, 0xe0,
+	0x44, 0x10, 0xf0, 0x7b, 0x05, 0x7d, 0x84, 0x7f, 0x86, 0x12, 0x36, 0x29,
+	0x22, 0xfb, 0xe5, 0x1c, 0x34, 0xf0, 0xfa, 0x7d, 0x10, 0x7f, 0x07, 0x22,
+	0x54, 0x01, 0xc4, 0x33, 0x54, 0xe0, 0xf5, 0xdb, 0x44, 0x08, 0xf5, 0xdb,
+	0x22, 0xf5, 0xdb, 0x75, 0xdb, 0x08, 0xf5, 0xdb, 0x75, 0xdb, 0x08, 0x22,
+	0xab, 0x07, 0xaa, 0x06, 0x7d, 0x10, 0x7f, 0x07, 0x12, 0x3e, 0xda, 0x7b,
+	0xff, 0x7d, 0x10, 0x7f, 0x07, 0x12, 0x3d, 0xd7, 0xef, 0x4e, 0x60, 0xf3,
+	0x22, 0x12, 0x44, 0xc2, 0x30, 0x0c, 0x03, 0x12, 0x42, 0x12, 0x78, 0xc4,
+	0xe6, 0xff, 0x60, 0x03, 0x12, 0x40, 0x25, 0x22, 0xe5, 0x19, 0x24, 0x17,
+	0x54, 0x1f, 0x44, 0x80, 0xff, 0x22, 0x74, 0x2a, 0x25, 0x19, 0xf8, 0xe6,
+	0x22, 0x12, 0x46, 0x72, 0x12, 0x46, 0x68, 0x90, 0x47, 0xfa, 0xe0, 0x54,
+	0xf8, 0x44, 0x02, 0xf0, 0x22, 0xe5, 0x7e, 0xae, 0x7d, 0x78, 0x04, 0x22,
+	0xce, 0xa2, 0xe7, 0x13, 0xce, 0x13, 0x22, 0xe4, 0x78, 0xc4, 0xf6, 0xc2,
+	0x0d, 0x78, 0xc1, 0xf6, 0x22, 0xc2, 0x0c, 0xc2, 0x0b, 0x22, 0x22,
+};
+
+static const u8 fw_patch_vsc8584[] = {
+	0xe8, 0x59, 0x02, 0xe8, 0x12, 0x02, 0xe8, 0x42, 0x02, 0xe8, 0x5a, 0x02,
+	0xe8, 0x5b, 0x02, 0xe8, 0x5c, 0xe5, 0x69, 0x54, 0x0f, 0x24, 0xf7, 0x60,
+	0x27, 0x24, 0xfc, 0x60, 0x23, 0x24, 0x08, 0x70, 0x14, 0xe5, 0x69, 0xae,
+	0x68, 0x78, 0x04, 0xce, 0xa2, 0xe7, 0x13, 0xce, 0x13, 0xd8, 0xf8, 0x7e,
+	0x00, 0x54, 0x0f, 0x80, 0x00, 0x7b, 0x01, 0x7a, 0x00, 0x7d, 0xee, 0x7f,
+	0x92, 0x12, 0x50, 0xee, 0x22, 0xe4, 0xf5, 0x10, 0x85, 0x10, 0xfb, 0x7d,
+	0x1c, 0xe4, 0xff, 0x12, 0x59, 0xea, 0x05, 0x10, 0xe5, 0x10, 0xc3, 0x94,
+	0x04, 0x40, 0xed, 0x22, 0x22, 0x22, 0x22, 0x22,
+};
+
+static int vsc8584_get_fw_crc(struct mii_dev *bus, int phy, u16 start,
+			      u16 *crc, const u8 *fw_patch, int fw_size)
+{
+	int ret;
+
+	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+		   MSCC_PHY_PAGE_EXT1);
+
+	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_VERIPHY_CNTL_2, start);
+	/* Add one byte to size for the one added by the patch_fw function */
+	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_VERIPHY_CNTL_3,
+		   fw_size + 1);
+
+	ret = vsc8584_cmd(bus, phy, PROC_CMD_CRC16);
+	if (ret)
+		goto out;
+
+	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+		   MSCC_PHY_PAGE_EXT1);
+
+	*crc = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_VERIPHY_CNTL_2);
+
+out:
+	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+		   MSCC_PHY_PAGE_STD);
+
+	return ret;
+}
+
+static int vsc8584_patch_fw(struct mii_dev *bus, int phy, const u8 *fw_patch,
+			    int fw_size)
+{
+	int i, ret;
+
+	ret = vsc8584_micro_assert_reset(bus, phy);
+	if (ret) {
+		pr_err("%s: failed to assert reset of micro\n", __func__);
+		return ret;
+	}
+
+	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+		   MSCC_PHY_PAGE_GPIO);
+
+	/*
+	 * Hold 8051 Micro in SW Reset, Enable auto incr address and patch clock
+	 * Disable the 8051 Micro clock
+	 */
+	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS,
+		   RUN_FROM_INT_ROM | AUTOINC_ADDR | PATCH_RAM_CLK |
+		   MICRO_CLK_EN | MICRO_CLK_DIVIDE(2));
+	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, READ_PRAM |
+		   INT_MEM_WRITE_EN | INT_MEM_DATA(2));
+	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_ADDR, 0x0000);
+
+	for (i = 0; i < fw_size; i++)
+		bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL,
+			   READ_PRAM | INT_MEM_WRITE_EN | fw_patch[i]);
+
+	/* Clear internal memory access */
+	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, READ_RAM);
+
+	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+		   MSCC_PHY_PAGE_STD);
+
+	return 0;
+}
+
+static bool vsc8574_is_serdes_init(struct mii_dev *bus, int phy)
+{
+	u16 reg;
+	bool ret;
+
+	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+		   MSCC_PHY_PAGE_GPIO);
+
+	reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_TRAP_ROM_ADDR(1));
+	if (reg != MSCC_TRAP_ROM_ADDR_SERDES_INIT) {
+		ret = false;
+		goto out;
+	}
+
+	reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_PATCH_RAM_ADDR(1));
+	if (reg != MSCC_PATCH_RAM_ADDR_SERDES_INIT) {
+		ret = false;
+		goto out;
+	}
+
+	reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL);
+	if (reg != EN_PATCH_RAM_TRAP_ADDR(1)) {
+		ret = false;
+		goto out;
+	}
+
+	reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS);
+	if ((MICRO_NSOFT_RESET | RUN_FROM_INT_ROM |  DW8051_CLK_EN |
+	     MICRO_CLK_EN) != (reg & MSCC_DW8051_VLD_MASK)) {
+		ret = false;
+		goto out;
+	}
+
+	ret = true;
+
+out:
+	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+		   MSCC_PHY_PAGE_GPIO);
+
+	return ret;
+}
+
+static int vsc8574_config_pre_init(struct phy_device *phydev)
+{
+	struct mii_dev *bus = phydev->bus;
+	u16 crc, reg, phy0, addr;
+	bool serdes_init;
+	int ret;
+
+	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+		  MSCC_PHY_PAGE_EXT1);
+	addr = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_4);
+	addr >>= PHY_CNTL_4_ADDR_POS;
+
+	reg = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_ACTIPHY_CNTL);
+	if (reg & PHY_ADDR_REVERSED)
+		phy0 = phydev->addr + addr;
+	else
+		phy0 = phydev->addr - addr;
+
+	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+		   MSCC_PHY_PAGE_STD);
+
+	/* all writes below are broadcasted to all PHYs in the same package */
+	reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS);
+	reg |= SMI_BROADCAST_WR_EN;
+	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS, reg);
+
+	/*
+	 * The below register writes are tweaking analog and electrical
+	 * configuration that were determined through characterization by PHY
+	 * engineers. These don't mean anything more than "these are the best
+	 * values".
+	 */
+	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_2, 0x0040);
+
+	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+		   MSCC_PHY_PAGE_TEST);
+
+	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_20, 0x4320);
+	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_24, 0x0c00);
+	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_9, 0x18ca);
+	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_5, 0x1b20);
+
+	reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8);
+	reg |= TR_CLK_DISABLE;
+	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8, reg);
+
+	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+		   MSCC_PHY_PAGE_TR);
+
+	vsc8584_csr_write(bus, phy0, 0x0fae, 0x000401bd);
+	vsc8584_csr_write(bus, phy0, 0x0fac, 0x000f000f);
+	vsc8584_csr_write(bus, phy0, 0x17a0, 0x00a0f147);
+	vsc8584_csr_write(bus, phy0, 0x0fe4, 0x00052f54);
+	vsc8584_csr_write(bus, phy0, 0x1792, 0x0027303d);
+	vsc8584_csr_write(bus, phy0, 0x07fe, 0x00000704);
+	vsc8584_csr_write(bus, phy0, 0x0fe0, 0x00060150);
+	vsc8584_csr_write(bus, phy0, 0x0f82, 0x0012b00a);
+	vsc8584_csr_write(bus, phy0, 0x0f80, 0x00000d74);
+	vsc8584_csr_write(bus, phy0, 0x02e0, 0x00000012);
+	vsc8584_csr_write(bus, phy0, 0x03a2, 0x00050208);
+	vsc8584_csr_write(bus, phy0, 0x03b2, 0x00009186);
+	vsc8584_csr_write(bus, phy0, 0x0fb0, 0x000e3700);
+	vsc8584_csr_write(bus, phy0, 0x1688, 0x00049f81);
+	vsc8584_csr_write(bus, phy0, 0x0fd2, 0x0000ffff);
+	vsc8584_csr_write(bus, phy0, 0x168a, 0x00039fa2);
+	vsc8584_csr_write(bus, phy0, 0x1690, 0x0020640b);
+	vsc8584_csr_write(bus, phy0, 0x0258, 0x00002220);
+	vsc8584_csr_write(bus, phy0, 0x025a, 0x00002a20);
+	vsc8584_csr_write(bus, phy0, 0x025c, 0x00003060);
+	vsc8584_csr_write(bus, phy0, 0x025e, 0x00003fa0);
+	vsc8584_csr_write(bus, phy0, 0x03a6, 0x0000e0f0);
+	vsc8584_csr_write(bus, phy0, 0x0f92, 0x00001489);
+	vsc8584_csr_write(bus, phy0, 0x16a2, 0x00007000);
+	vsc8584_csr_write(bus, phy0, 0x16a6, 0x00071448);
+	vsc8584_csr_write(bus, phy0, 0x16a0, 0x00eeffdd);
+	vsc8584_csr_write(bus, phy0, 0x0fe8, 0x0091b06c);
+	vsc8584_csr_write(bus, phy0, 0x0fea, 0x00041600);
+	vsc8584_csr_write(bus, phy0, 0x16b0, 0x00eeff00);
+	vsc8584_csr_write(bus, phy0, 0x16b2, 0x00007000);
+	vsc8584_csr_write(bus, phy0, 0x16b4, 0x00000814);
+	vsc8584_csr_write(bus, phy0, 0x0f90, 0x00688980);
+	vsc8584_csr_write(bus, phy0, 0x03a4, 0x0000d8f0);
+	vsc8584_csr_write(bus, phy0, 0x0fc0, 0x00000400);
+	vsc8584_csr_write(bus, phy0, 0x07fa, 0x0050100f);
+	vsc8584_csr_write(bus, phy0, 0x0796, 0x00000003);
+	vsc8584_csr_write(bus, phy0, 0x07f8, 0x00c3ff98);
+	vsc8584_csr_write(bus, phy0, 0x0fa4, 0x0018292a);
+	vsc8584_csr_write(bus, phy0, 0x168c, 0x00d2c46f);
+	vsc8584_csr_write(bus, phy0, 0x17a2, 0x00000620);
+	vsc8584_csr_write(bus, phy0, 0x16a4, 0x0013132f);
+	vsc8584_csr_write(bus, phy0, 0x16a8, 0x00000000);
+	vsc8584_csr_write(bus, phy0, 0x0ffc, 0x00c0a028);
+	vsc8584_csr_write(bus, phy0, 0x0fec, 0x00901c09);
+	vsc8584_csr_write(bus, phy0, 0x0fee, 0x0004a6a1);
+	vsc8584_csr_write(bus, phy0, 0x0ffe, 0x00b01807);
+
+	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+			MSCC_PHY_PAGE_EXT2);
+
+	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_CU_PMD_TX_CNTL, 0x028e);
+
+	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+		   MSCC_PHY_PAGE_TR);
+
+	vsc8584_csr_write(bus, phy0, 0x0486, 0x0008a518);
+	vsc8584_csr_write(bus, phy0, 0x0488, 0x006dc696);
+	vsc8584_csr_write(bus, phy0, 0x048a, 0x00000912);
+	vsc8584_csr_write(bus, phy0, 0x048e, 0x00000db6);
+	vsc8584_csr_write(bus, phy0, 0x049c, 0x00596596);
+	vsc8584_csr_write(bus, phy0, 0x049e, 0x00000514);
+	vsc8584_csr_write(bus, phy0, 0x04a2, 0x00410280);
+	vsc8584_csr_write(bus, phy0, 0x04a4, 0x00000000);
+	vsc8584_csr_write(bus, phy0, 0x04a6, 0x00000000);
+	vsc8584_csr_write(bus, phy0, 0x04a8, 0x00000000);
+	vsc8584_csr_write(bus, phy0, 0x04aa, 0x00000000);
+	vsc8584_csr_write(bus, phy0, 0x04ae, 0x007df7dd);
+	vsc8584_csr_write(bus, phy0, 0x04b0, 0x006d95d4);
+	vsc8584_csr_write(bus, phy0, 0x04b2, 0x00492410);
+
+	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+		   MSCC_PHY_PAGE_TEST);
+
+	reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8);
+	reg &= ~TR_CLK_DISABLE;
+	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8, reg);
+
+	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+			MSCC_PHY_PAGE_STD);
+
+	/* end of write broadcasting */
+	reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS);
+	reg &= ~SMI_BROADCAST_WR_EN;
+	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS, reg);
+
+	ret = vsc8584_get_fw_crc(bus, phy0,
+				 MSCC_VSC8574_REVB_INT8051_FW_START_ADDR, &crc,
+				 fw_patch_vsc8574,
+				 ARRAY_SIZE(fw_patch_vsc8574));
+	if (ret)
+		goto out;
+
+	if (crc == MSCC_VSC8574_REVB_INT8051_FW_CRC) {
+		serdes_init = vsc8574_is_serdes_init(bus, phy0);
+
+		if (!serdes_init) {
+			ret = vsc8584_micro_assert_reset(bus, phy0);
+			if (ret) {
+				pr_err("failed to assert reset of micro\n");
+				return ret;
+			}
+		}
+	} else {
+		pr_debug("FW CRC is not the expected one, patching FW\n");
+
+		serdes_init = false;
+
+		if (vsc8584_patch_fw(bus, phy0, fw_patch_vsc8574,
+				     ARRAY_SIZE(fw_patch_vsc8574)))
+			pr_warn("failed to patch FW, expect non-optimal device\n");
+	}
+
+	if (!serdes_init) {
+		bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+				MSCC_PHY_PAGE_GPIO);
+
+		bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_TRAP_ROM_ADDR(1),
+			   MSCC_TRAP_ROM_ADDR_SERDES_INIT);
+		bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PATCH_RAM_ADDR(1),
+			   MSCC_PATCH_RAM_ADDR_SERDES_INIT);
+
+		bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL,
+				EN_PATCH_RAM_TRAP_ADDR(1));
+
+		vsc8584_micro_deassert_reset(bus, phy0, false);
+
+		ret = vsc8584_get_fw_crc(bus, phy0,
+					 MSCC_VSC8574_REVB_INT8051_FW_START_ADDR,
+					 &crc, fw_patch_vsc8574,
+					 ARRAY_SIZE(fw_patch_vsc8574));
+		if (ret)
+			goto out;
+
+		if (crc != MSCC_VSC8574_REVB_INT8051_FW_CRC)
+			pr_warn("FW CRC after patching is not the expected one, expect non-optimal device\n");
+	}
+
+	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+		   MSCC_PHY_PAGE_GPIO);
+
+	ret = vsc8584_cmd(bus, phy0, PROC_CMD_1588_DEFAULT_INIT |
+			  PROC_CMD_PHY_INIT);
+
+out:
+	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+			MSCC_PHY_PAGE_STD);
+
+	return ret;
+}
+
+static int vsc8584_config_pre_init(struct phy_device *phydev)
+{
+	struct mii_dev *bus = phydev->bus;
+	u16 reg, crc, phy0, addr;
+	int ret;
+
+	if ((phydev->phy_id & MSCC_DEV_REV_MASK) != VSC8584_REVB) {
+		pr_warn("VSC8584 revA not officially supported, skipping firmware patching. Use at your own risk.\n");
+		return 0;
+	}
+
+	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+		  MSCC_PHY_PAGE_EXT1);
+	addr = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_4);
+	addr >>= PHY_CNTL_4_ADDR_POS;
+
+	reg = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_ACTIPHY_CNTL);
+	if (reg & PHY_ADDR_REVERSED)
+		phy0 = phydev->addr + addr;
+	else
+		phy0 = phydev->addr - addr;
+
+	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+		   MSCC_PHY_PAGE_STD);
+
+	/* all writes below are broadcasted to all PHYs in the same package */
+	reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS);
+	reg |= SMI_BROADCAST_WR_EN;
+	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS, reg);
+
+	/*
+	 * The below register writes are tweaking analog and electrical
+	 * configuration that were determined through characterization by PHY
+	 * engineers. These don't mean anything more than "these are the best
+	 * values".
+	 */
+	reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_BYPASS_CONTROL);
+	reg |= PARALLEL_DET_IGNORE_ADVERTISED;
+	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_BYPASS_CONTROL, reg);
+
+	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+		   MSCC_PHY_PAGE_EXT3);
+
+	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_SERDES_TX_CRC_ERR_CNT,
+		   0x2000);
+
+	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+		   MSCC_PHY_PAGE_TEST);
+
+	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_5, 0x1f20);
+
+	reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8);
+	reg |= TR_CLK_DISABLE;
+	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8, reg);
+
+	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+		   MSCC_PHY_PAGE_TR);
+
+	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16, 0xafa4);
+
+	reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18);
+	reg &= ~0x007f;
+	reg |= 0x0019;
+	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18, reg);
+
+	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16, 0x8fa4);
+
+	vsc8584_csr_write(bus, phy0, 0x07fa, 0x0050100f);
+	vsc8584_csr_write(bus, phy0, 0x1688, 0x00049f81);
+	vsc8584_csr_write(bus, phy0, 0x0f90, 0x00688980);
+	vsc8584_csr_write(bus, phy0, 0x03a4, 0x0000d8f0);
+	vsc8584_csr_write(bus, phy0, 0x0fc0, 0x00000400);
+	vsc8584_csr_write(bus, phy0, 0x0f82, 0x0012b002);
+	vsc8584_csr_write(bus, phy0, 0x1686, 0x00000004);
+	vsc8584_csr_write(bus, phy0, 0x168c, 0x00d2c46f);
+	vsc8584_csr_write(bus, phy0, 0x17a2, 0x00000620);
+	vsc8584_csr_write(bus, phy0, 0x16a0, 0x00eeffdd);
+	vsc8584_csr_write(bus, phy0, 0x16a6, 0x00071448);
+	vsc8584_csr_write(bus, phy0, 0x16a4, 0x0013132f);
+	vsc8584_csr_write(bus, phy0, 0x16a8, 0x00000000);
+	vsc8584_csr_write(bus, phy0, 0x0ffc, 0x00c0a028);
+	vsc8584_csr_write(bus, phy0, 0x0fe8, 0x0091b06c);
+	vsc8584_csr_write(bus, phy0, 0x0fea, 0x00041600);
+	vsc8584_csr_write(bus, phy0, 0x0f80, 0x00fffaff);
+	vsc8584_csr_write(bus, phy0, 0x0fec, 0x00901809);
+	vsc8584_csr_write(bus, phy0, 0x0ffe, 0x00b01007);
+	vsc8584_csr_write(bus, phy0, 0x16b0, 0x00eeff00);
+	vsc8584_csr_write(bus, phy0, 0x16b2, 0x00007000);
+	vsc8584_csr_write(bus, phy0, 0x16b4, 0x00000814);
+
+	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+		   MSCC_PHY_PAGE_EXT2);
+
+	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_CU_PMD_TX_CNTL, 0x028e);
+
+	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+		   MSCC_PHY_PAGE_TR);
+
+	vsc8584_csr_write(bus, phy0, 0x0486, 0x0008a518);
+	vsc8584_csr_write(bus, phy0, 0x0488, 0x006dc696);
+	vsc8584_csr_write(bus, phy0, 0x048a, 0x00000912);
+
+	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+		   MSCC_PHY_PAGE_TEST);
+
+	reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8);
+	reg &= ~TR_CLK_DISABLE;
+	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8, reg);
+
+	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+		   MSCC_PHY_PAGE_STD);
+
+	/* end of write broadcasting */
+	reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS);
+	reg &= ~SMI_BROADCAST_WR_EN;
+	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS, reg);
+
+	ret = vsc8584_get_fw_crc(bus, phy0,
+				 MSCC_VSC8584_REVB_INT8051_FW_START_ADDR, &crc,
+				 fw_patch_vsc8584,
+				 ARRAY_SIZE(fw_patch_vsc8584));
+	if (ret)
+		goto out;
+
+	if (crc != MSCC_VSC8584_REVB_INT8051_FW_CRC) {
+		debug("FW CRC is not the expected one, patching FW...\n");
+		if (vsc8584_patch_fw(bus, phy0, fw_patch_vsc8584,
+				     ARRAY_SIZE(fw_patch_vsc8584)))
+			pr_warn("failed to patch FW, expect non-optimal device\n");
+	}
+
+	vsc8584_micro_deassert_reset(bus, phy0, false);
+
+	ret = vsc8584_get_fw_crc(bus, phy0,
+				 MSCC_VSC8584_REVB_INT8051_FW_START_ADDR, &crc,
+				 fw_patch_vsc8584,
+				 ARRAY_SIZE(fw_patch_vsc8584));
+	if (ret)
+		goto out;
+
+	if (crc != MSCC_VSC8584_REVB_INT8051_FW_CRC)
+		pr_warn("FW CRC after patching is not the expected one, expect non-optimal device\n");
+
+	ret = vsc8584_micro_assert_reset(bus, phy0);
+	if (ret)
+		goto out;
+
+	vsc8584_micro_deassert_reset(bus, phy0, true);
+
+out:
+	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+		   MSCC_PHY_PAGE_STD);
+
+	return ret;
+}
 
 static int mscc_vsc8531_vsc8541_init_scripts(struct phy_device *phydev)
 {
@@ -457,6 +1328,108 @@
 	return genphy_config_aneg(phydev);
 }
 
+static int vsc8584_config_init(struct phy_device *phydev)
+{
+	struct vsc85xx_priv *priv = phydev->priv;
+	int ret;
+	u16 addr;
+	u16 reg_val;
+	u16 val;
+
+	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+		  MSCC_PHY_PAGE_EXT1);
+	addr = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_4);
+	addr >>= PHY_CNTL_4_ADDR_POS;
+
+	ret = priv->config_pre(phydev);
+	if (ret)
+		return ret;
+
+	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+		  MSCC_PHY_PAGE_GPIO);
+
+	if (phydev->interface == PHY_INTERFACE_MODE_QSGMII)
+		val = MAC_CFG_QSGMII;
+	else
+		val = MAC_CFG_SGMII;
+
+	reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_MAC_CFG_FASTLINK);
+	reg_val &= ~MAC_CFG_MASK;
+	reg_val |= val;
+	ret = phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_MAC_CFG_FASTLINK,
+			reg_val);
+	if (ret)
+		return ret;
+
+	reg_val = PROC_CMD_MCB_ACCESS_MAC_CONF | PROC_CMD_RST_CONF_PORT |
+		PROC_CMD_READ_MOD_WRITE_PORT;
+	if (phydev->interface == PHY_INTERFACE_MODE_QSGMII)
+		reg_val |= PROC_CMD_QSGMII_MAC;
+	else
+		reg_val |= PROC_CMD_SGMII_MAC;
+
+	ret = vsc8584_cmd(phydev->bus, phydev->addr, reg_val);
+	if (ret)
+		return ret;
+
+	mdelay(10);
+
+	/* Disable SerDes for 100Base-FX */
+	ret = vsc8584_cmd(phydev->bus, phydev->addr, PROC_CMD_FIBER_MEDIA_CONF |
+			  PROC_CMD_FIBER_PORT(addr) | PROC_CMD_FIBER_DISABLE |
+			  PROC_CMD_READ_MOD_WRITE_PORT |
+			  PROC_CMD_RST_CONF_PORT | PROC_CMD_FIBER_100BASE_FX);
+	if (ret)
+		return ret;
+
+	/* Disable SerDes for 1000Base-X */
+	ret = vsc8584_cmd(phydev->bus, phydev->addr, PROC_CMD_FIBER_MEDIA_CONF |
+			  PROC_CMD_FIBER_PORT(addr) | PROC_CMD_FIBER_DISABLE |
+			  PROC_CMD_READ_MOD_WRITE_PORT |
+			  PROC_CMD_RST_CONF_PORT | PROC_CMD_FIBER_1000BASE_X);
+	if (ret)
+		return ret;
+
+	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+		  MSCC_PHY_PAGE_STD);
+	reg_val = phy_read(phydev, MDIO_DEVAD_NONE,
+			   MSCC_PHY_EXT_PHY_CNTL_1_REG);
+	reg_val &= ~(MEDIA_OP_MODE_MASK | VSC8584_MAC_IF_SELECTION_MASK);
+	reg_val |= MEDIA_OP_MODE_COPPER |
+		(VSC8584_MAC_IF_SELECTION_SGMII <<
+		 VSC8584_MAC_IF_SELECTION_POS);
+	ret = phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_1_REG,
+			reg_val);
+
+	ret = mscc_phy_soft_reset(phydev);
+	if (ret != 0)
+		return ret;
+
+	return genphy_config(phydev);
+}
+
+static struct vsc85xx_priv vsc8574_priv = {
+	.config_pre = vsc8574_config_pre_init,
+};
+
+static int vsc8574_config(struct phy_device *phydev)
+{
+	phydev->priv = &vsc8574_priv;
+
+	return vsc8584_config_init(phydev);
+}
+
+static struct vsc85xx_priv vsc8584_priv = {
+	.config_pre = vsc8584_config_pre_init,
+};
+
+static int vsc8584_config(struct phy_device *phydev)
+{
+	phydev->priv = &vsc8584_priv;
+
+	return vsc8584_config_init(phydev);
+}
+
 static struct phy_driver VSC8530_driver = {
 	.name = "Microsemi VSC8530",
 	.uid = PHY_ID_VSC8530,
@@ -497,12 +1470,34 @@
 	.shutdown = &genphy_shutdown,
 };
 
+static struct phy_driver VSC8574_driver = {
+	.name = "Microsemi VSC8574",
+	.uid = PHY_ID_VSC8574,
+	.mask = 0x000ffff0,
+	.features = PHY_GBIT_FEATURES,
+	.config = &vsc8574_config,
+	.startup = &mscc_startup,
+	.shutdown = &genphy_shutdown,
+};
+
+static struct phy_driver VSC8584_driver = {
+	.name = "Microsemi VSC8584",
+	.uid = PHY_ID_VSC8584,
+	.mask = 0x000ffff0,
+	.features = PHY_GBIT_FEATURES,
+	.config = &vsc8584_config,
+	.startup = &mscc_startup,
+	.shutdown = &genphy_shutdown,
+};
+
 int phy_mscc_init(void)
 {
 	phy_register(&VSC8530_driver);
 	phy_register(&VSC8531_driver);
 	phy_register(&VSC8540_driver);
 	phy_register(&VSC8541_driver);
+	phy_register(&VSC8574_driver);
+	phy_register(&VSC8584_driver);
 
 	return 0;
 }
diff --git a/drivers/net/ti/Kconfig b/drivers/net/ti/Kconfig
new file mode 100644
index 0000000..82bc9f5
--- /dev/null
+++ b/drivers/net/ti/Kconfig
@@ -0,0 +1,20 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+
+config DRIVER_TI_CPSW
+	bool "TI Common Platform Ethernet Switch"
+	select PHYLIB
+	help
+	  This driver supports the TI three port switch gigabit ethernet
+	  subsystem found in the TI SoCs.
+
+config DRIVER_TI_EMAC
+	bool "TI Davinci EMAC"
+	help
+	   Support for davinci emac
+
+config DRIVER_TI_KEYSTONE_NET
+	bool "TI Keystone 2 Ethernet"
+	help
+	   This driver supports the TI Keystone 2 Ethernet subsystem
diff --git a/drivers/net/ti/Makefile b/drivers/net/ti/Makefile
new file mode 100644
index 0000000..ee3e4eb
--- /dev/null
+++ b/drivers/net/ti/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+
+obj-$(CONFIG_DRIVER_TI_CPSW) += cpsw.o cpsw-common.o cpsw_mdio.o
+obj-$(CONFIG_DRIVER_TI_EMAC) += davinci_emac.o
+obj-$(CONFIG_DRIVER_TI_KEYSTONE_NET) += keystone_net.o cpsw_mdio.o
diff --git a/drivers/net/cpsw-common.c b/drivers/net/ti/cpsw-common.c
similarity index 100%
rename from drivers/net/cpsw-common.c
rename to drivers/net/ti/cpsw-common.c
diff --git a/drivers/net/cpsw.c b/drivers/net/ti/cpsw.c
similarity index 90%
rename from drivers/net/cpsw.c
rename to drivers/net/ti/cpsw.c
index 8e2a48c..f5fd02e 100644
--- a/drivers/net/cpsw.c
+++ b/drivers/net/ti/cpsw.c
@@ -1,16 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * CPSW Ethernet Switch Driver
  *
- * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation version 2.
- *
- * This program is distributed "as is" WITHOUT ANY WARRANTY of any
- * kind, whether express or implied; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * Copyright (C) 2010-2018 Texas Instruments Incorporated - http://www.ti.com/
  */
 
 #include <common.h>
@@ -29,11 +21,11 @@
 #include <dm.h>
 #include <fdt_support.h>
 
+#include "cpsw_mdio.h"
+
 DECLARE_GLOBAL_DATA_PTR;
 
 #define BITMASK(bits)		(BIT(bits) - 1)
-#define PHY_REG_MASK		0x1f
-#define PHY_ID_MASK		0x1f
 #define NUM_DESCS		(PKTBUFSRX * 2)
 #define PKT_MIN			60
 #define PKT_MAX			(1500 + 14 + 4 + 4)
@@ -84,37 +76,8 @@
  * unexpected controller lock ups.  Ideally, we should never ever hit this
  * scenario in practice.
  */
-#define MDIO_TIMEOUT            100 /* msecs */
 #define CPDMA_TIMEOUT		100 /* msecs */
 
-struct cpsw_mdio_regs {
-	u32	version;
-	u32	control;
-#define CONTROL_IDLE		BIT(31)
-#define CONTROL_ENABLE		BIT(30)
-
-	u32	alive;
-	u32	link;
-	u32	linkintraw;
-	u32	linkintmasked;
-	u32	__reserved_0[2];
-	u32	userintraw;
-	u32	userintmasked;
-	u32	userintmaskset;
-	u32	userintmaskclr;
-	u32	__reserved_1[20];
-
-	struct {
-		u32		access;
-		u32		physel;
-#define USERACCESS_GO		BIT(31)
-#define USERACCESS_WRITE	BIT(30)
-#define USERACCESS_ACK		BIT(29)
-#define USERACCESS_READ		(0)
-#define USERACCESS_DATA		(0xffff)
-	} user[0];
-};
-
 struct cpsw_regs {
 	u32	id_ver;
 	u32	control;
@@ -492,100 +455,6 @@
 	__raw_writel(tmp, priv->ale_regs + offset);
 }
 
-static struct cpsw_mdio_regs *mdio_regs;
-
-/* wait until hardware is ready for another user access */
-static inline u32 wait_for_user_access(void)
-{
-	u32 reg = 0;
-	int timeout = MDIO_TIMEOUT;
-
-	while (timeout-- &&
-	((reg = __raw_readl(&mdio_regs->user[0].access)) & USERACCESS_GO))
-		udelay(10);
-
-	if (timeout == -1) {
-		printf("wait_for_user_access Timeout\n");
-		return -ETIMEDOUT;
-	}
-	return reg;
-}
-
-/* wait until hardware state machine is idle */
-static inline void wait_for_idle(void)
-{
-	int timeout = MDIO_TIMEOUT;
-
-	while (timeout-- &&
-		((__raw_readl(&mdio_regs->control) & CONTROL_IDLE) == 0))
-		udelay(10);
-
-	if (timeout == -1)
-		printf("wait_for_idle Timeout\n");
-}
-
-static int cpsw_mdio_read(struct mii_dev *bus, int phy_id,
-				int dev_addr, int phy_reg)
-{
-	int data;
-	u32 reg;
-
-	if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK)
-		return -EINVAL;
-
-	wait_for_user_access();
-	reg = (USERACCESS_GO | USERACCESS_READ | (phy_reg << 21) |
-	       (phy_id << 16));
-	__raw_writel(reg, &mdio_regs->user[0].access);
-	reg = wait_for_user_access();
-
-	data = (reg & USERACCESS_ACK) ? (reg & USERACCESS_DATA) : -1;
-	return data;
-}
-
-static int cpsw_mdio_write(struct mii_dev *bus, int phy_id, int dev_addr,
-				int phy_reg, u16 data)
-{
-	u32 reg;
-
-	if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK)
-		return -EINVAL;
-
-	wait_for_user_access();
-	reg = (USERACCESS_GO | USERACCESS_WRITE | (phy_reg << 21) |
-		   (phy_id << 16) | (data & USERACCESS_DATA));
-	__raw_writel(reg, &mdio_regs->user[0].access);
-	wait_for_user_access();
-
-	return 0;
-}
-
-static void cpsw_mdio_init(const char *name, u32 mdio_base, u32 div)
-{
-	struct mii_dev *bus = mdio_alloc();
-
-	mdio_regs = (struct cpsw_mdio_regs *)mdio_base;
-
-	/* set enable and clock divider */
-	__raw_writel(div | CONTROL_ENABLE, &mdio_regs->control);
-
-	/*
-	 * wait for scan logic to settle:
-	 * the scan time consists of (a) a large fixed component, and (b) a
-	 * small component that varies with the mii bus frequency.  These
-	 * were estimated using measurements at 1.1 and 2.2 MHz on tnetv107x
-	 * silicon.  Since the effect of (b) was found to be largely
-	 * negligible, we keep things simple here.
-	 */
-	udelay(1000);
-
-	bus->read = cpsw_mdio_read;
-	bus->write = cpsw_mdio_write;
-	strcpy(bus->name, name);
-
-	mdio_register(bus);
-}
-
 /* Set a self-clearing bit in a register, and wait for it to clear */
 static inline void setbit_and_wait_for_clear32(void *addr)
 {
@@ -1011,7 +880,7 @@
 static void cpsw_phy_addr_update(struct cpsw_priv *priv)
 {
 	struct cpsw_platform_data *data = &priv->data;
-	u16 alive = mdio_regs->alive & GENMASK(15, 0);
+	u16 alive = cpsw_mdio_get_alive(priv->bus);
 	int active = data->active_slave;
 	int new_addr = ffs(alive) - 1;
 
@@ -1052,11 +921,12 @@
 		idx = idx + 1;
 	}
 
-	cpsw_mdio_init(priv->dev->name, data->mdio_base, data->mdio_div);
+	priv->bus = cpsw_mdio_init(priv->dev->name, data->mdio_base, 0, 0);
+	if (!priv->bus)
+		return -EFAULT;
 
 	cpsw_phy_addr_update(priv);
 
-	priv->bus = miiphy_get_dev_by_name(priv->dev->name);
 	for_active_slave(slave, priv)
 		cpsw_phy_init(priv, slave);
 
diff --git a/drivers/net/ti/cpsw_mdio.c b/drivers/net/ti/cpsw_mdio.c
new file mode 100644
index 0000000..70f547e
--- /dev/null
+++ b/drivers/net/ti/cpsw_mdio.c
@@ -0,0 +1,203 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * CPSW MDIO generic driver for TI AMxx/K2x/EMAC devices.
+ *
+ * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <miiphy.h>
+#include <wait_bit.h>
+
+struct cpsw_mdio_regs {
+	u32	version;
+	u32	control;
+#define CONTROL_IDLE		BIT(31)
+#define CONTROL_ENABLE		BIT(30)
+#define CONTROL_FAULT		BIT(19)
+#define CONTROL_FAULT_ENABLE	BIT(18)
+#define CONTROL_DIV_MASK	GENMASK(15, 0)
+
+	u32	alive;
+	u32	link;
+	u32	linkintraw;
+	u32	linkintmasked;
+	u32	__reserved_0[2];
+	u32	userintraw;
+	u32	userintmasked;
+	u32	userintmaskset;
+	u32	userintmaskclr;
+	u32	__reserved_1[20];
+
+	struct {
+		u32		access;
+		u32		physel;
+#define USERACCESS_GO		BIT(31)
+#define USERACCESS_WRITE	BIT(30)
+#define USERACCESS_ACK		BIT(29)
+#define USERACCESS_READ		(0)
+#define USERACCESS_PHY_REG_SHIFT	(21)
+#define USERACCESS_PHY_ADDR_SHIFT	(16)
+#define USERACCESS_DATA		GENMASK(15, 0)
+	} user[0];
+};
+
+#define CPSW_MDIO_DIV_DEF	0xff
+#define PHY_REG_MASK		0x1f
+#define PHY_ID_MASK		0x1f
+
+/*
+ * This timeout definition is a worst-case ultra defensive measure against
+ * unexpected controller lock ups.  Ideally, we should never ever hit this
+ * scenario in practice.
+ */
+#define CPSW_MDIO_TIMEOUT            100 /* msecs */
+
+struct cpsw_mdio {
+	struct cpsw_mdio_regs *regs;
+	struct mii_dev *bus;
+	int div;
+};
+
+/* wait until hardware is ready for another user access */
+static int cpsw_mdio_wait_for_user_access(struct cpsw_mdio *mdio)
+{
+	return wait_for_bit_le32(&mdio->regs->user[0].access,
+				 USERACCESS_GO, false,
+				 CPSW_MDIO_TIMEOUT, false);
+}
+
+static int cpsw_mdio_read(struct mii_dev *bus, int phy_id,
+			  int dev_addr, int phy_reg)
+{
+	struct cpsw_mdio *mdio = bus->priv;
+	int data, ret;
+	u32 reg;
+
+	if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK)
+		return -EINVAL;
+
+	ret = cpsw_mdio_wait_for_user_access(mdio);
+	if (ret)
+		return ret;
+	reg = (USERACCESS_GO | USERACCESS_READ |
+	       (phy_reg << USERACCESS_PHY_REG_SHIFT) |
+	       (phy_id << USERACCESS_PHY_ADDR_SHIFT));
+	writel(reg, &mdio->regs->user[0].access);
+	ret = cpsw_mdio_wait_for_user_access(mdio);
+	if (ret)
+		return ret;
+
+	reg = readl(&mdio->regs->user[0].access);
+	data = (reg & USERACCESS_ACK) ? (reg & USERACCESS_DATA) : -1;
+	return data;
+}
+
+static int cpsw_mdio_write(struct mii_dev *bus, int phy_id, int dev_addr,
+			   int phy_reg, u16 data)
+{
+	struct cpsw_mdio *mdio = bus->priv;
+	u32 reg;
+	int ret;
+
+	if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK)
+		return -EINVAL;
+
+	ret = cpsw_mdio_wait_for_user_access(mdio);
+	if (ret)
+		return ret;
+	reg = (USERACCESS_GO | USERACCESS_WRITE |
+	       (phy_reg << USERACCESS_PHY_REG_SHIFT) |
+	       (phy_id << USERACCESS_PHY_ADDR_SHIFT) |
+	       (data & USERACCESS_DATA));
+	writel(reg, &mdio->regs->user[0].access);
+
+	return cpsw_mdio_wait_for_user_access(mdio);
+}
+
+u32 cpsw_mdio_get_alive(struct mii_dev *bus)
+{
+	struct cpsw_mdio *mdio = bus->priv;
+	u32 val;
+
+	val = readl(&mdio->regs->control);
+	return val & GENMASK(15, 0);
+}
+
+struct mii_dev *cpsw_mdio_init(const char *name, u32 mdio_base,
+			       u32 bus_freq, int fck_freq)
+{
+	struct cpsw_mdio *cpsw_mdio;
+	int ret;
+
+	cpsw_mdio = calloc(1, sizeof(*cpsw_mdio));
+	if (!cpsw_mdio) {
+		debug("failed to alloc cpsw_mdio\n");
+		return NULL;
+	}
+
+	cpsw_mdio->bus = mdio_alloc();
+	if (!cpsw_mdio->bus) {
+		debug("failed to alloc mii bus\n");
+		free(cpsw_mdio);
+		return NULL;
+	}
+
+	cpsw_mdio->regs = (struct cpsw_mdio_regs *)mdio_base;
+
+	if (!bus_freq || !fck_freq)
+		cpsw_mdio->div = CPSW_MDIO_DIV_DEF;
+	else
+		cpsw_mdio->div = (fck_freq / bus_freq) - 1;
+	cpsw_mdio->div &= CONTROL_DIV_MASK;
+
+	/* set enable and clock divider */
+	writel(cpsw_mdio->div | CONTROL_ENABLE | CONTROL_FAULT |
+	       CONTROL_FAULT_ENABLE, &cpsw_mdio->regs->control);
+	wait_for_bit_le32(&cpsw_mdio->regs->control,
+			  CONTROL_IDLE, false, CPSW_MDIO_TIMEOUT, true);
+
+	/*
+	 * wait for scan logic to settle:
+	 * the scan time consists of (a) a large fixed component, and (b) a
+	 * small component that varies with the mii bus frequency.  These
+	 * were estimated using measurements at 1.1 and 2.2 MHz on tnetv107x
+	 * silicon.  Since the effect of (b) was found to be largely
+	 * negligible, we keep things simple here.
+	 */
+	mdelay(1);
+
+	cpsw_mdio->bus->read = cpsw_mdio_read;
+	cpsw_mdio->bus->write = cpsw_mdio_write;
+	cpsw_mdio->bus->priv = cpsw_mdio;
+	snprintf(cpsw_mdio->bus->name, sizeof(cpsw_mdio->bus->name), name);
+
+	ret = mdio_register(cpsw_mdio->bus);
+	if (ret < 0) {
+		debug("failed to register mii bus\n");
+		goto free_bus;
+	}
+
+	return cpsw_mdio->bus;
+
+free_bus:
+	mdio_free(cpsw_mdio->bus);
+	free(cpsw_mdio);
+	return NULL;
+}
+
+void cpsw_mdio_free(struct mii_dev *bus)
+{
+	struct cpsw_mdio *mdio = bus->priv;
+	u32 reg;
+
+	/* disable mdio */
+	reg = readl(&mdio->regs->control);
+	reg &= ~CONTROL_ENABLE;
+	writel(reg, &mdio->regs->control);
+
+	mdio_unregister(bus);
+	mdio_free(bus);
+	free(mdio);
+}
diff --git a/drivers/net/ti/cpsw_mdio.h b/drivers/net/ti/cpsw_mdio.h
new file mode 100644
index 0000000..4a76d4e
--- /dev/null
+++ b/drivers/net/ti/cpsw_mdio.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * CPSW MDIO generic driver API for TI AMxx/K2x/EMAC devices.
+ *
+ * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+#ifndef CPSW_MDIO_H_
+#define CPSW_MDIO_H_
+
+struct cpsw_mdio;
+
+struct mii_dev *cpsw_mdio_init(const char *name, u32 mdio_base,
+			       u32 bus_freq, int fck_freq);
+void cpsw_mdio_free(struct mii_dev *bus);
+u32 cpsw_mdio_get_alive(struct mii_dev *bus);
+
+#endif /* CPSW_MDIO_H_ */
diff --git a/drivers/net/davinci_emac.c b/drivers/net/ti/davinci_emac.c
similarity index 100%
rename from drivers/net/davinci_emac.c
rename to drivers/net/ti/davinci_emac.c
diff --git a/drivers/net/davinci_emac.h b/drivers/net/ti/davinci_emac.h
similarity index 100%
rename from drivers/net/davinci_emac.h
rename to drivers/net/ti/davinci_emac.h
diff --git a/drivers/net/keystone_net.c b/drivers/net/ti/keystone_net.c
similarity index 68%
rename from drivers/net/keystone_net.c
rename to drivers/net/ti/keystone_net.c
index d4d909b..a3ba91c 100644
--- a/drivers/net/keystone_net.c
+++ b/drivers/net/ti/keystone_net.c
@@ -22,13 +22,9 @@
 #include <asm/ti-common/keystone_serdes.h>
 #include <asm/arch/psc_defs.h>
 
-DECLARE_GLOBAL_DATA_PTR;
+#include "cpsw_mdio.h"
 
-#ifndef CONFIG_DM_ETH
-unsigned int emac_open;
-static struct mii_dev *mdio_bus;
-static unsigned int sys_has_mdio = 1;
-#endif
+DECLARE_GLOBAL_DATA_PTR;
 
 #ifdef KEYSTONE2_EMAC_GIG_ENABLE
 #define emac_gigabit_enable(x)	keystone2_eth_gigabit_enable(x)
@@ -43,17 +39,6 @@
 
 static u8 rx_buffs[RX_BUFF_NUMS * RX_BUFF_LEN] __aligned(16);
 
-#ifndef CONFIG_DM_ETH
-struct rx_buff_desc net_rx_buffs = {
-	.buff_ptr	= rx_buffs,
-	.num_buffs	= RX_BUFF_NUMS,
-	.buff_len	= RX_BUFF_LEN,
-	.rx_flow	= 22,
-};
-#endif
-
-#ifdef CONFIG_DM_ETH
-
 enum link_type {
 	LINK_TYPE_SGMII_MAC_TO_MAC_AUTO		= 0,
 	LINK_TYPE_SGMII_MAC_TO_PHY_MODE		= 1,
@@ -83,7 +68,7 @@
 #define DEVICE_EMACSW_BASE(base, x)	((base) + EMAC_EMACSW_PORT_BASE_OFS +  \
 					 (x) * 0x30)
 
-#elif defined CONFIG_KSNET_NETCP_V1_5
+#elif defined(CONFIG_KSNET_NETCP_V1_5)
 
 #define EMAC_EMACSW_PORT_BASE_OFS	0x222000
 
@@ -113,126 +98,26 @@
 	bool				emac_open;
 	bool				has_mdio;
 };
-#endif
 
-/* MDIO */
-
-static int keystone2_mdio_reset(struct mii_dev *bus)
-{
-	u_int32_t clkdiv;
-	struct mdio_regs *adap_mdio = bus->priv;
-
-	clkdiv = (EMAC_MDIO_BUS_FREQ / EMAC_MDIO_CLOCK_FREQ) - 1;
-
-	writel((clkdiv & 0xffff) | MDIO_CONTROL_ENABLE |
-	       MDIO_CONTROL_FAULT | MDIO_CONTROL_FAULT_ENABLE,
-	       &adap_mdio->control);
-
-	while (readl(&adap_mdio->control) & MDIO_CONTROL_IDLE)
-		;
-
-	return 0;
-}
-
-/**
- * keystone2_mdio_read - read a PHY register via MDIO interface.
- * Blocks until operation is complete.
- */
-static int keystone2_mdio_read(struct mii_dev *bus,
-			       int addr, int devad, int reg)
-{
-	int tmp;
-	struct mdio_regs *adap_mdio = bus->priv;
-
-	while (readl(&adap_mdio->useraccess0) & MDIO_USERACCESS0_GO)
-		;
-
-	writel(MDIO_USERACCESS0_GO | MDIO_USERACCESS0_WRITE_READ |
-	       ((reg & 0x1f) << 21) | ((addr & 0x1f) << 16),
-	       &adap_mdio->useraccess0);
-
-	/* Wait for command to complete */
-	while ((tmp = readl(&adap_mdio->useraccess0)) & MDIO_USERACCESS0_GO)
-		;
-
-	if (tmp & MDIO_USERACCESS0_ACK)
-		return tmp & 0xffff;
-
-	return -1;
-}
-
-/**
- * keystone2_mdio_write - write to a PHY register via MDIO interface.
- * Blocks until operation is complete.
- */
-static int keystone2_mdio_write(struct mii_dev *bus,
-				int addr, int devad, int reg, u16 val)
-{
-	struct mdio_regs *adap_mdio = bus->priv;
-
-	while (readl(&adap_mdio->useraccess0) & MDIO_USERACCESS0_GO)
-		;
-
-	writel(MDIO_USERACCESS0_GO | MDIO_USERACCESS0_WRITE_WRITE |
-	       ((reg & 0x1f) << 21) | ((addr & 0x1f) << 16) |
-	       (val & 0xffff), &adap_mdio->useraccess0);
-
-	/* Wait for command to complete */
-	while (readl(&adap_mdio->useraccess0) & MDIO_USERACCESS0_GO)
-		;
-
-	return 0;
-}
-
-#ifndef CONFIG_DM_ETH
-static void  __attribute__((unused))
-	keystone2_eth_gigabit_enable(struct eth_device *dev)
-{
-	u_int16_t data;
-	struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv;
-
-	if (sys_has_mdio) {
-		data = keystone2_mdio_read(mdio_bus, eth_priv->phy_addr,
-					   MDIO_DEVAD_NONE, 0);
-		/* speed selection MSB */
-		if (!(data & (1 << 6)))
-			return;
-	}
-
-	/*
-	 * Check if link detected is giga-bit
-	 * If Gigabit mode detected, enable gigbit in MAC
-	 */
-	writel(readl(DEVICE_EMACSL_BASE(eth_priv->slave_port - 1) +
-		     CPGMACSL_REG_CTL) |
-	       EMAC_MACCONTROL_GIGFORCE | EMAC_MACCONTROL_GIGABIT_ENABLE,
-	       DEVICE_EMACSL_BASE(eth_priv->slave_port - 1) + CPGMACSL_REG_CTL);
-}
-#else
 static void  __attribute__((unused))
 	keystone2_eth_gigabit_enable(struct udevice *dev)
 {
 	struct ks2_eth_priv *priv = dev_get_priv(dev);
-	u_int16_t data;
-
-	if (priv->has_mdio) {
-		data = keystone2_mdio_read(priv->mdio_bus, priv->phy_addr,
-					   MDIO_DEVAD_NONE, 0);
-		/* speed selection MSB */
-		if (!(data & (1 << 6)))
-			return;
-	}
 
 	/*
 	 * Check if link detected is giga-bit
 	 * If Gigabit mode detected, enable gigbit in MAC
 	 */
+	if (priv->has_mdio) {
+		if (priv->phydev->speed != 1000)
+			return;
+	}
+
 	writel(readl(DEVICE_EMACSL_BASE(priv->slave_port - 1) +
 		     CPGMACSL_REG_CTL) |
 	       EMAC_MACCONTROL_GIGFORCE | EMAC_MACCONTROL_GIGABIT_ENABLE,
 	       DEVICE_EMACSL_BASE(priv->slave_port - 1) + CPGMACSL_REG_CTL);
 }
-#endif
 
 #ifdef CONFIG_SOC_K2G
 int keystone_rgmii_config(struct phy_device *phy_dev)
@@ -497,246 +382,6 @@
 }
 #endif
 
-#ifndef CONFIG_DM_ETH
-
-int keystone2_eth_read_mac_addr(struct eth_device *dev)
-{
-	struct eth_priv_t *eth_priv;
-	u32 maca = 0;
-	u32 macb = 0;
-
-	eth_priv = (struct eth_priv_t *)dev->priv;
-
-	/* Read the e-fuse mac address */
-	if (eth_priv->slave_port == 1) {
-		maca = __raw_readl(MAC_ID_BASE_ADDR);
-		macb = __raw_readl(MAC_ID_BASE_ADDR + 4);
-	}
-
-	dev->enetaddr[0] = (macb >>  8) & 0xff;
-	dev->enetaddr[1] = (macb >>  0) & 0xff;
-	dev->enetaddr[2] = (maca >> 24) & 0xff;
-	dev->enetaddr[3] = (maca >> 16) & 0xff;
-	dev->enetaddr[4] = (maca >>  8) & 0xff;
-	dev->enetaddr[5] = (maca >>  0) & 0xff;
-
-	return 0;
-}
-
-int32_t cpmac_drv_send(u32 *buffer, int num_bytes, int slave_port_num)
-{
-	if (num_bytes < EMAC_MIN_ETHERNET_PKT_SIZE)
-		num_bytes = EMAC_MIN_ETHERNET_PKT_SIZE;
-
-	return ksnav_send(&netcp_pktdma, buffer,
-			  num_bytes, (slave_port_num) << 16);
-}
-
-/* Eth device open */
-static int keystone2_eth_open(struct eth_device *dev, bd_t *bis)
-{
-	struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv;
-	struct phy_device *phy_dev = eth_priv->phy_dev;
-
-	debug("+ emac_open\n");
-
-	net_rx_buffs.rx_flow	= eth_priv->rx_flow;
-
-	sys_has_mdio =
-		(eth_priv->sgmii_link_type == SGMII_LINK_MAC_PHY) ? 1 : 0;
-
-	if (sys_has_mdio)
-		keystone2_mdio_reset(mdio_bus);
-
-#ifdef CONFIG_SOC_K2G
-	keystone_rgmii_config(phy_dev);
-#else
-	keystone_sgmii_config(phy_dev, eth_priv->slave_port - 1,
-			      eth_priv->sgmii_link_type);
-#endif
-
-	udelay(10000);
-
-	/* On chip switch configuration */
-	ethss_config(target_get_switch_ctl(), SWITCH_MAX_PKT_SIZE);
-
-	/* TODO: add error handling code */
-	if (qm_init()) {
-		printf("ERROR: qm_init()\n");
-		return -1;
-	}
-	if (ksnav_init(&netcp_pktdma, &net_rx_buffs)) {
-		qm_close();
-		printf("ERROR: netcp_init()\n");
-		return -1;
-	}
-
-	/*
-	 * Streaming switch configuration. If not present this
-	 * statement is defined to void in target.h.
-	 * If present this is usually defined to a series of register writes
-	 */
-	hw_config_streaming_switch();
-
-	if (sys_has_mdio) {
-		keystone2_mdio_reset(mdio_bus);
-
-		phy_startup(phy_dev);
-		if (phy_dev->link == 0) {
-			ksnav_close(&netcp_pktdma);
-			qm_close();
-			return -1;
-		}
-	}
-
-	emac_gigabit_enable(dev);
-
-	ethss_start();
-
-	debug("- emac_open\n");
-
-	emac_open = 1;
-
-	return 0;
-}
-
-/* Eth device close */
-void keystone2_eth_close(struct eth_device *dev)
-{
-	struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv;
-	struct phy_device *phy_dev = eth_priv->phy_dev;
-
-	debug("+ emac_close\n");
-
-	if (!emac_open)
-		return;
-
-	ethss_stop();
-
-	ksnav_close(&netcp_pktdma);
-	qm_close();
-	phy_shutdown(phy_dev);
-
-	emac_open = 0;
-
-	debug("- emac_close\n");
-}
-
-/*
- * This function sends a single packet on the network and returns
- * positive number (number of bytes transmitted) or negative for error
- */
-static int keystone2_eth_send_packet(struct eth_device *dev,
-					void *packet, int length)
-{
-	int ret_status = -1;
-	struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv;
-	struct phy_device *phy_dev = eth_priv->phy_dev;
-
-	genphy_update_link(phy_dev);
-	if (phy_dev->link == 0)
-		return -1;
-
-	if (cpmac_drv_send((u32 *)packet, length, eth_priv->slave_port) != 0)
-		return ret_status;
-
-	return length;
-}
-
-/*
- * This function handles receipt of a packet from the network
- */
-static int keystone2_eth_rcv_packet(struct eth_device *dev)
-{
-	void *hd;
-	int  pkt_size;
-	u32  *pkt;
-
-	hd = ksnav_recv(&netcp_pktdma, &pkt, &pkt_size);
-	if (hd == NULL)
-		return 0;
-
-	net_process_received_packet((uchar *)pkt, pkt_size);
-
-	ksnav_release_rxhd(&netcp_pktdma, hd);
-
-	return pkt_size;
-}
-
-#ifdef CONFIG_MCAST_TFTP
-static int keystone2_eth_bcast_addr(struct eth_device *dev, u32 ip, u8 set)
-{
-	return 0;
-}
-#endif
-
-/*
- * This function initializes the EMAC hardware.
- */
-int keystone2_emac_initialize(struct eth_priv_t *eth_priv)
-{
-	int res;
-	struct eth_device *dev;
-	struct phy_device *phy_dev;
-	struct mdio_regs *adap_mdio = (struct mdio_regs *)EMAC_MDIO_BASE_ADDR;
-
-	dev = malloc(sizeof(struct eth_device));
-	if (dev == NULL)
-		return -1;
-
-	memset(dev, 0, sizeof(struct eth_device));
-
-	strcpy(dev->name, eth_priv->int_name);
-	dev->priv = eth_priv;
-
-	keystone2_eth_read_mac_addr(dev);
-
-	dev->iobase		= 0;
-	dev->init		= keystone2_eth_open;
-	dev->halt		= keystone2_eth_close;
-	dev->send		= keystone2_eth_send_packet;
-	dev->recv		= keystone2_eth_rcv_packet;
-#ifdef CONFIG_MCAST_TFTP
-	dev->mcast		= keystone2_eth_bcast_addr;
-#endif
-
-	eth_register(dev);
-
-	/* Register MDIO bus if it's not registered yet */
-	if (!mdio_bus) {
-		mdio_bus	= mdio_alloc();
-		mdio_bus->read	= keystone2_mdio_read;
-		mdio_bus->write	= keystone2_mdio_write;
-		mdio_bus->reset	= keystone2_mdio_reset;
-		mdio_bus->priv	= (void *)EMAC_MDIO_BASE_ADDR;
-		strcpy(mdio_bus->name, "ethernet-mdio");
-
-		res = mdio_register(mdio_bus);
-		if (res)
-			return res;
-	}
-
-#ifndef CONFIG_SOC_K2G
-	keystone2_net_serdes_setup();
-#endif
-
-	/* Create phy device and bind it with driver */
-#ifdef CONFIG_KSNET_MDIO_PHY_CONFIG_ENABLE
-	phy_dev = phy_connect(mdio_bus, eth_priv->phy_addr,
-			      dev, eth_priv->phy_if);
-	phy_config(phy_dev);
-#else
-	phy_dev = phy_find_by_mask(mdio_bus, 1 << eth_priv->phy_addr,
-				   eth_priv->phy_if);
-	phy_dev->dev = dev;
-#endif
-	eth_priv->phy_dev = phy_dev;
-
-	return 0;
-}
-
-#else
-
 static int ks2_eth_start(struct udevice *dev)
 {
 	struct ks2_eth_priv *priv = dev_get_priv(dev);
@@ -768,8 +413,6 @@
 	hw_config_streaming_switch();
 
 	if (priv->has_mdio) {
-		keystone2_mdio_reset(priv->mdio_bus);
-
 		phy_startup(priv->phydev);
 		if (priv->phydev->link == 0) {
 			pr_err("phy startup failed\n");
@@ -889,9 +532,9 @@
 {
 	struct ks2_eth_priv *priv = dev_get_priv(dev);
 	struct mii_dev *mdio_bus;
-	int ret;
 
 	priv->dev = dev;
+	priv->emac_open = false;
 
 	/* These clock enables has to be moved to common location */
 	if (cpu_is_k2g())
@@ -910,45 +553,36 @@
 	if (cpu_is_k2e() || cpu_is_k2l())
 		pll_pa_clk_sel();
 
-
 	priv->net_rx_buffs.buff_ptr = rx_buffs;
 	priv->net_rx_buffs.num_buffs = RX_BUFF_NUMS;
 	priv->net_rx_buffs.buff_len = RX_BUFF_LEN;
 
 	if (priv->slave_port == 1) {
+#ifndef CONFIG_SOC_K2G
+		keystone2_net_serdes_setup();
+#endif
 		/*
 		 * Register MDIO bus for slave 0 only, other slave have
 		 * to re-use the same
 		 */
-		mdio_bus = mdio_alloc();
+		mdio_bus = cpsw_mdio_init("ethernet-mdio",
+					  (u32)priv->mdio_base,
+					  EMAC_MDIO_CLOCK_FREQ,
+					  EMAC_MDIO_BUS_FREQ);
 		if (!mdio_bus) {
 			pr_err("MDIO alloc failed\n");
 			return -ENOMEM;
 		}
 		priv->mdio_bus = mdio_bus;
-		mdio_bus->read	= keystone2_mdio_read;
-		mdio_bus->write	= keystone2_mdio_write;
-		mdio_bus->reset	= keystone2_mdio_reset;
-		mdio_bus->priv	= priv->mdio_base;
-		sprintf(mdio_bus->name, "ethernet-mdio");
-
-		ret = mdio_register(mdio_bus);
-		if (ret) {
-			pr_err("MDIO bus register failed\n");
-			return ret;
-		}
 	} else {
 		/* Get the MDIO bus from slave 0 device */
 		struct ks2_eth_priv *parent_priv;
 
 		parent_priv = dev_get_priv(dev->parent);
 		priv->mdio_bus = parent_priv->mdio_bus;
+		priv->mdio_base = parent_priv->mdio_base;
 	}
 
-#ifndef CONFIG_SOC_K2G
-	keystone2_net_serdes_setup();
-#endif
-
 	priv->netcp_pktdma = &netcp_pktdma;
 
 	if (priv->has_mdio) {
@@ -964,9 +598,7 @@
 {
 	struct ks2_eth_priv *priv = dev_get_priv(dev);
 
-	free(priv->phydev);
-	mdio_unregister(priv->mdio_bus);
-	mdio_free(priv->mdio_bus);
+	cpsw_mdio_free(priv->mdio_bus);
 
 	return 0;
 }
@@ -1167,4 +799,3 @@
 	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
 	.flags = DM_FLAG_ALLOC_PRIV_DMA,
 };
-#endif
diff --git a/include/configs/ti_armv7_keystone2.h b/include/configs/ti_armv7_keystone2.h
index cc823c5..5e504f6 100644
--- a/include/configs/ti_armv7_keystone2.h
+++ b/include/configs/ti_armv7_keystone2.h
@@ -128,7 +128,6 @@
 #define CONFIG_KSNAV_NETCP_PDMA_TX_SND_QUEUE	KS2_NETCP_PDMA_TX_SND_QUEUE
 
 /* Keystone net */
-#define CONFIG_DRIVER_TI_KEYSTONE_NET
 #define CONFIG_KSNET_MAC_ID_BASE		KS2_MAC_ID_BASE_ADDR
 #define CONFIG_KSNET_NETCP_BASE			KS2_NETCP_BASE
 #define CONFIG_KSNET_SERDES_SGMII_BASE		KS2_SGMII_SERDES_BASE
diff --git a/include/netdev.h b/include/netdev.h
index 5500162..0a1a3a2 100644
--- a/include/netdev.h
+++ b/include/netdev.h
@@ -43,7 +43,6 @@
 int fec_initialize (bd_t *bis);
 int fecmxc_initialize(bd_t *bis);
 int fecmxc_initialize_multi(bd_t *bis, int dev_id, int phy_id, uint32_t addr);
-int ftgmac100_initialize(bd_t *bits);
 int ftmac100_initialize(bd_t *bits);
 int ftmac110_initialize(bd_t *bits);
 void gt6426x_eth_initialize(bd_t *bis);