Merge branch 'master_sh/gen4/initial' of https://source.denx.de/u-boot/custodians/u-boot-sh

- Initial R-Car Generation 4 support
diff --git a/arch/arm/lib/lib1funcs.S b/arch/arm/lib/lib1funcs.S
index de15d09e..a1f44d9 100644
--- a/arch/arm/lib/lib1funcs.S
+++ b/arch/arm/lib/lib1funcs.S
@@ -419,4 +419,21 @@
 	ret	lr
 ENDPROC(__gnu_thumb1_case_uhi)
 .popsection
+
+/* Taken and adapted from: https://github.com/gcc-mirror/gcc/blob/4f181f9c7ee3efc509d185fdfda33be9018f1611/libgcc/config/arm/lib1funcs.S#L2156 */
+.pushsection .text.__gnu_thumb1_case_si, "ax"
+ENTRY(__gnu_thumb1_case_si)
+	push	{r0, r1}
+	mov	r1, lr
+	adds	r1, r1, #2	/* Align to word.  */
+	lsrs	r1, r1, #2
+	lsls	r0, r0, #2
+	lsls	r1, r1, #2
+	ldr	r0, [r1, r0]
+	adds	r0, r0, r1
+	mov	lr, r0
+	pop	{r0, r1}
+	mov	pc, lr		/* We know we were called from thumb code.  */
+ENDPROC(__gnu_thumb1_case_si)
+.popsection
 #endif
diff --git a/cmd/2048.c b/cmd/2048.c
new file mode 100644
index 0000000..fa60aa9
--- /dev/null
+++ b/cmd/2048.c
@@ -0,0 +1,397 @@
+// SPDX-License-Identifier: MIT
+// SPDX-FileCopyrightText: © 2014 Maurits van der Schee
+
+/* Console version of the game "2048" for GNU/Linux */
+
+#include <common.h>
+#include <cli.h>
+#include <command.h>
+#include <rand.h>
+#include <linux/delay.h>
+
+#define SIZE 4
+static uint score;
+
+static void getColor(uint value, char *color, size_t length)
+{
+	u8 original[] = {
+		8, 255, 1, 255, 2, 255, 3, 255,
+		4, 255, 5, 255, 6, 255, 7, 255,
+		9, 0, 10, 0, 11, 0, 12, 0, 13,
+		0, 14, 0, 255, 0, 255, 0};
+	u8 *scheme = original;
+	u8 *background = scheme + 0;
+	u8 *foreground = scheme + 1;
+
+	if (value > 0) {
+		while (value >>= 1) {
+			if (background + 2 < scheme + sizeof(original)) {
+				background += 2;
+				foreground += 2;
+			}
+		}
+	}
+	snprintf(color, length, "\033[38;5;%d;48;5;%dm", *foreground,
+		 *background);
+}
+
+static void drawBoard(u16 board[SIZE][SIZE])
+{
+	int x, y;
+	char color[40], reset[] = "\033[0m";
+
+	printf("\033[H");
+	printf("2048.c %17d pts\n\n", score);
+
+	for (y = 0; y < SIZE; y++) {
+		for (x = 0; x < SIZE; x++) {
+			getColor(board[x][y], color, 40);
+			printf("%s", color);
+			printf("       ");
+			printf("%s", reset);
+		}
+		printf("\n");
+		for (x = 0; x < SIZE; x++) {
+			getColor(board[x][y], color, 40);
+			printf("%s", color);
+			if (board[x][y] != 0) {
+				char s[8];
+				s8 t;
+
+				snprintf(s, 8, "%u", board[x][y]);
+				t = 7 - strlen(s);
+				printf("%*s%s%*s", t - t / 2, "", s, t / 2, "");
+			} else {
+				printf("   ·   ");
+			}
+			printf("%s", reset);
+		}
+		printf("\n");
+		for (x = 0; x < SIZE; x++) {
+			getColor(board[x][y], color, 40);
+			printf("%s", color);
+			printf("       ");
+			printf("%s", reset);
+		}
+		printf("\n");
+	}
+	printf("\n");
+	printf("        ←, ↑, →, ↓ or q        \n");
+	printf("\033[A");
+}
+
+static int8_t findTarget(u16 array[SIZE], int x, int stop)
+{
+	int t;
+
+	/* if the position is already on the first, don't evaluate */
+	if (x == 0)
+		return x;
+	for (t = x - 1; t >= 0; t--) {
+		if (array[t]) {
+			if (array[t] != array[x]) {
+				/* merge is not possible, take next position */
+				return t + 1;
+			}
+			return t;
+		}
+
+		/* we should not slide further, return this one */
+		if (t == stop)
+			return t;
+	}
+	/* we did not find a */
+	return x;
+}
+
+static bool slideArray(u16 array[SIZE])
+{
+	bool success = false;
+	int x, t, stop = 0;
+
+	for (x = 0; x < SIZE; x++) {
+		if (array[x] != 0) {
+			t = findTarget(array, x, stop);
+			/*
+			 * if target is not original position, then move or
+			 * merge
+			 */
+			if (t != x) {
+				/*
+				 * if target is not zero, set stop to avoid
+				 * double merge
+				 */
+				if (array[t]) {
+					score += array[t] + array[x];
+					stop = t + 1;
+				}
+				array[t] += array[x];
+				array[x] = 0;
+				success = true;
+			}
+		}
+	}
+	return success;
+}
+
+static void rotateBoard(u16 board[SIZE][SIZE])
+{
+	s8 i, j, n = SIZE;
+	int tmp;
+
+	for (i = 0; i < n / 2; i++) {
+		for (j = i; j < n - i - 1; j++) {
+			tmp = board[i][j];
+			board[i][j] = board[j][n - i - 1];
+			board[j][n - i - 1] = board[n - i - 1][n - j - 1];
+			board[n - i - 1][n - j - 1] = board[n - j - 1][i];
+			board[n - j - 1][i] = tmp;
+		}
+	}
+}
+
+static bool moveUp(u16 board[SIZE][SIZE])
+{
+	bool success = false;
+	int x;
+
+	for (x = 0; x < SIZE; x++)
+		success |= slideArray(board[x]);
+
+	return success;
+}
+
+static bool moveLeft(u16 board[SIZE][SIZE])
+{
+	bool success;
+
+	rotateBoard(board);
+	success = moveUp(board);
+	rotateBoard(board);
+	rotateBoard(board);
+	rotateBoard(board);
+	return success;
+}
+
+static bool moveDown(u16 board[SIZE][SIZE])
+{
+	bool success;
+
+	rotateBoard(board);
+	rotateBoard(board);
+	success = moveUp(board);
+	rotateBoard(board);
+	rotateBoard(board);
+	return success;
+}
+
+static bool moveRight(u16 board[SIZE][SIZE])
+{
+	bool success;
+
+	rotateBoard(board);
+	rotateBoard(board);
+	rotateBoard(board);
+	success = moveUp(board);
+	rotateBoard(board);
+	return success;
+}
+
+static bool findPairDown(u16 board[SIZE][SIZE])
+{
+	bool success = false;
+	int x, y;
+
+	for (x = 0; x < SIZE; x++) {
+		for (y = 0; y < SIZE - 1; y++) {
+			if (board[x][y] == board[x][y + 1])
+				return true;
+		}
+	}
+
+	return success;
+}
+
+static int16_t countEmpty(u16 board[SIZE][SIZE])
+{
+	int x, y;
+	int count = 0;
+
+	for (x = 0; x < SIZE; x++) {
+		for (y = 0; y < SIZE; y++) {
+			if (board[x][y] == 0)
+				count++;
+		}
+	}
+	return count;
+}
+
+static bool gameEnded(u16 board[SIZE][SIZE])
+{
+	bool ended = true;
+
+	if (countEmpty(board) > 0)
+		return false;
+	if (findPairDown(board))
+		return false;
+	rotateBoard(board);
+	if (findPairDown(board))
+		ended = false;
+	rotateBoard(board);
+	rotateBoard(board);
+	rotateBoard(board);
+
+	return ended;
+}
+
+static void addRandom(u16 board[SIZE][SIZE])
+{
+	int x, y;
+	int r, len = 0;
+	u16 n, list[SIZE * SIZE][2];
+
+	for (x = 0; x < SIZE; x++) {
+		for (y = 0; y < SIZE; y++) {
+			if (board[x][y] == 0) {
+				list[len][0] = x;
+				list[len][1] = y;
+				len++;
+			}
+		}
+	}
+
+	if (len > 0) {
+		r = rand() % len;
+		x = list[r][0];
+		y = list[r][1];
+		n = ((rand() % 10) / 9 + 1) * 2;
+		board[x][y] = n;
+	}
+}
+
+static int test(void)
+{
+	u16 array[SIZE];
+	u16 data[] = {
+		0, 0, 0, 2,	2, 0, 0, 0,
+		0, 0, 2, 2,	4, 0, 0, 0,
+		0, 2, 0, 2,	4, 0, 0, 0,
+		2, 0, 0, 2,	4, 0, 0, 0,
+		2, 0, 2, 0,	4, 0, 0, 0,
+		2, 2, 2, 0,	4, 2, 0, 0,
+		2, 0, 2, 2,	4, 2, 0, 0,
+		2, 2, 0, 2,	4, 2, 0, 0,
+		2, 2, 2, 2,	4, 4, 0, 0,
+		4, 4, 2, 2,	8, 4, 0, 0,
+		2, 2, 4, 4,	4, 8, 0, 0,
+		8, 0, 2, 2,	8, 4, 0, 0,
+		4, 0, 2, 2,	4, 4, 0, 0
+	};
+	u16 *in, *out;
+	u16 t, tests;
+	int i;
+	bool success = true;
+
+	tests = (sizeof(data) / sizeof(data[0])) / (2 * SIZE);
+	for (t = 0; t < tests; t++) {
+		in = data + t * 2 * SIZE;
+		out = in + SIZE;
+		for (i = 0; i < SIZE; i++)
+			array[i] = in[i];
+		slideArray(array);
+		for (i = 0; i < SIZE; i++) {
+			if (array[i] != out[i])
+				success = false;
+		}
+		if (!success) {
+			for (i = 0; i < SIZE; i++)
+				printf("%d ", in[i]);
+			printf(" = > ");
+			for (i = 0; i < SIZE; i++)
+				printf("%d ", array[i]);
+			printf("expected ");
+			for (i = 0; i < SIZE; i++)
+				printf("%d ", in[i]);
+			printf(" = > ");
+			for (i = 0; i < SIZE; i++)
+				printf("%d ", out[i]);
+			printf("\n");
+			break;
+		}
+	}
+	if (success)
+		printf("All %u tests executed successfully\n", tests);
+
+	return !success;
+}
+
+static int do_2048(struct cmd_tbl *cmdtp, int flag, int argc,
+		   char *const argv[])
+{
+	struct cli_ch_state cch_s, *cch = &cch_s;
+	u16 board[SIZE][SIZE];
+	bool success;
+
+	if (argc == 2 && strcmp(argv[1], "test") == 0)
+		return test();
+
+	score = 0;
+
+	printf("\033[?25l\033[2J\033[H");
+
+	memset(board, 0, sizeof(board));
+	addRandom(board);
+	addRandom(board);
+	drawBoard(board);
+	cli_ch_init(cch);
+	while (true) {
+		int c;
+
+		c = cli_ch_process(cch, 0);
+		if (!c) {
+			c = getchar();
+			c = cli_ch_process(cch, c);
+		}
+		switch (c) {
+		case CTL_CH('b'): /* left arrow */
+			success = moveLeft(board);
+			break;
+		case CTL_CH('f'): /* right arrow */
+			success = moveRight(board);
+			break;
+		case CTL_CH('p'):/* up arrow */
+			success = moveUp(board);
+			break;
+		case CTL_CH('n'): /* down arrow */
+			success = moveDown(board);
+			break;
+		default:
+			success = false;
+		}
+		if (success) {
+			drawBoard(board);
+			mdelay(150);
+			addRandom(board);
+			drawBoard(board);
+			if (gameEnded(board)) {
+				printf("         GAME OVER          \n");
+				break;
+			}
+		}
+		if (c == 'q') {
+			printf("            QUIT            \n");
+			break;
+		}
+	}
+
+	printf("\033[?25h");
+
+	return 0;
+}
+
+U_BOOT_CMD(
+	2048,	2,	1,	do_2048,
+	"The 2048 game",
+	"Use your arrow keys to move the tiles. When two tiles with "
+	"the same number touch, they merge into one!"
+);
diff --git a/cmd/Kconfig b/cmd/Kconfig
index bab35fc..e45b884 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -1446,7 +1446,8 @@
 
 config CMD_SCSI
 	bool "scsi - Access to SCSI devices"
-	default y if SCSI
+	depends on SCSI
+	default y
 	help
 	  This provides a 'scsi' command which provides access to SCSI (Small
 	  Computer System Interface) devices. The command provides a way to
@@ -1940,6 +1941,17 @@
 
 menu "Misc commands"
 
+config CMD_2048
+	bool "Play 2048"
+	help
+	  This is a simple sliding block puzzle game designed by Italian web
+	  developer Gabriele Cirulli. The game's objective is to slide numbered
+	  tiles on a grid to combine them to create a tile with the number
+	  2048.
+
+	  This needs ANSI support on your terminal to work. It is not fully
+	  functional on a video device.
+
 config CMD_BMP
 	bool "Enable 'bmp' command"
 	depends on VIDEO
diff --git a/cmd/Makefile b/cmd/Makefile
index 054ef42..6c37521 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -12,6 +12,7 @@
 obj-y += version.o
 
 # command
+obj-$(CONFIG_CMD_2048) += 2048.o
 obj-$(CONFIG_CMD_ACPI) += acpi.o
 obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o
 obj-$(CONFIG_CMD_AES) += aes.o
diff --git a/cmd/date.c b/cmd/date.c
index 58505e6..fe9c8c6 100644
--- a/cmd/date.c
+++ b/cmd/date.c
@@ -98,7 +98,7 @@
 				puts("## Get date failed\n");
 			}
 		}
-		/* FALL TROUGH */
+		fallthrough;
 	case 1:			/* get date & time */
 #ifdef CONFIG_DM_RTC
 		rcode = dm_rtc_get(dev, &tm);
diff --git a/cmd/pci.c b/cmd/pci.c
index 58a7475..78b661d 100644
--- a/cmd/pci.c
+++ b/cmd/pci.c
@@ -517,6 +517,7 @@
 			addr = hextoul(argv[3], NULL);
 		if (argc > 4)
 			value = hextoul(argv[4], NULL);
+		fallthrough;
 	case 'h':		/* header */
 	case 'b':		/* bars */
 		if (argc < 3)
diff --git a/cmd/regulator.c b/cmd/regulator.c
index ed4996d..8988c90 100644
--- a/cmd/regulator.c
+++ b/cmd/regulator.c
@@ -37,6 +37,7 @@
 			printf("Can't get the regulator: %s!\n", name);
 			return failure(ret);
 		}
+		fallthrough;
 	case 1:
 		if (!currdev) {
 			printf("Regulator device is not set!\n\n");
diff --git a/configs/controlcenterdc_defconfig b/configs/controlcenterdc_defconfig
index 9c906ed..9940258 100644
--- a/configs/controlcenterdc_defconfig
+++ b/configs/controlcenterdc_defconfig
@@ -72,6 +72,7 @@
 CONFIG_NET_RETRY_COUNT=50
 CONFIG_USE_ROOTPATH=y
 CONFIG_SPL_OF_TRANSLATE=y
+CONFIG_SYS_SATA_MAX_PORTS=2
 CONFIG_SCSI_AHCI=y
 CONFIG_DM_PCA953X=y
 CONFIG_DM_I2C=y
diff --git a/configs/highbank_defconfig b/configs/highbank_defconfig
index f045757..4eac7b2 100644
--- a/configs/highbank_defconfig
+++ b/configs/highbank_defconfig
@@ -30,6 +30,7 @@
 CONFIG_MISC_INIT_R=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_ENV_IS_IN_NVRAM=y
+CONFIG_SYS_SATA_MAX_PORTS=5
 CONFIG_SCSI_AHCI=y
 CONFIG_SYS_64BIT_LBA=y
 CONFIG_BOOTCOUNT_LIMIT=y
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 3a1f14c..ca95b2c 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -340,3 +340,4 @@
 CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
+CONFIG_CMD_2048=y
diff --git a/doc/arch/m68k.rst b/doc/arch/m68k.rst
index a9180fd..8474ece 100644
--- a/doc/arch/m68k.rst
+++ b/doc/arch/m68k.rst
@@ -5,7 +5,7 @@
 
 History
 -------
-* November 02, 2017	Angelo Dureghello <angelo@sysam.it>
+* November 02, 2017	Angelo Dureghello <angelo@kernel-space.org>
 * August   08, 2005	Jens Scharsig <esw@bus-elektronik.de>
   MCF5282 implementation without preloader
 * January  12, 2004	<josef.baumgartner@telex.de>
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 3fe53d6..049f7ef 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -20,6 +20,14 @@
 
 	  See also CMD_SATA which provides command-line support.
 
+config SYS_SATA_MAX_PORTS
+	int "Maximum supported SATA ports"
+	depends on SCSI_AHCI && !DM_SCSI
+	default 1
+	help
+	  Sets the maximum number of ports to scan when looking for devices.
+	  Ports from 0 to (this value - 1) are scanned.
+
 config LIBATA
 	bool
 	help
@@ -37,6 +45,7 @@
 	bool "Support for PCI-based AHCI controller"
 	depends on PCI
 	depends on DM_SCSI
+	depends on SCSI_AHCI
 	help
 	  Enables support for the PCI-based AHCI controller.
 
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 272c48b..6998b82 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -211,8 +211,8 @@
 	      uc_priv->cap, uc_priv->port_map, uc_priv->n_ports);
 
 #if !defined(CONFIG_DM_SCSI)
-	if (uc_priv->n_ports > CONFIG_SYS_SCSI_MAX_SCSI_ID)
-		uc_priv->n_ports = CONFIG_SYS_SCSI_MAX_SCSI_ID;
+	if (uc_priv->n_ports > CONFIG_SYS_SATA_MAX_PORTS)
+		uc_priv->n_ports = CONFIG_SYS_SATA_MAX_PORTS;
 #endif
 
 	for (i = 0; i < uc_priv->n_ports; i++) {
diff --git a/drivers/net/mvpp2.c b/drivers/net/mvpp2.c
index 1bad50d..f407d8f 100644
--- a/drivers/net/mvpp2.c
+++ b/drivers/net/mvpp2.c
@@ -2871,7 +2871,6 @@
 
 	switch (port->phy_interface) {
 	case PHY_INTERFACE_MODE_SGMII:
-	case PHY_INTERFACE_MODE_SGMII_2500:
 		val |= MVPP2_GMAC_INBAND_AN_MASK;
 		break;
 	case PHY_INTERFACE_MODE_1000BASEX:
@@ -2939,7 +2938,6 @@
 		val &= ~MVPP2_GMAC_GMII_LB_EN_MASK;
 
 	if (port->phy_interface == PHY_INTERFACE_MODE_SGMII ||
-	    port->phy_interface == PHY_INTERFACE_MODE_SGMII_2500 ||
 	    port->phy_interface == PHY_INTERFACE_MODE_1000BASEX ||
 	    port->phy_interface == PHY_INTERFACE_MODE_2500BASEX)
 		val |= MVPP2_GMAC_PCS_LB_EN_MASK;
@@ -3027,48 +3025,6 @@
 	return 0;
 }
 
-static void gop_gmac_sgmii2_5_cfg(struct mvpp2_port *port)
-{
-	u32 val, thresh;
-
-	/*
-	 * Configure minimal level of the Tx FIFO before the lower part
-	 * starts to read a packet
-	 */
-	thresh = MVPP2_SGMII2_5_TX_FIFO_MIN_TH;
-	val = readl(port->base + MVPP2_GMAC_PORT_FIFO_CFG_1_REG);
-	val &= ~MVPP2_GMAC_TX_FIFO_MIN_TH_ALL_MASK;
-	val |= MVPP2_GMAC_TX_FIFO_MIN_TH_MASK(thresh);
-	writel(val, port->base + MVPP2_GMAC_PORT_FIFO_CFG_1_REG);
-
-	/* Disable bypass of sync module */
-	val = readl(port->base + MVPP2_GMAC_CTRL_4_REG);
-	val |= MVPP2_GMAC_CTRL4_SYNC_BYPASS_MASK;
-	/* configure DP clock select according to mode */
-	val |= MVPP2_GMAC_CTRL4_DP_CLK_SEL_MASK;
-	/* configure QSGMII bypass according to mode */
-	val |= MVPP2_GMAC_CTRL4_QSGMII_BYPASS_ACTIVE_MASK;
-	writel(val, port->base + MVPP2_GMAC_CTRL_4_REG);
-
-	val = readl(port->base + MVPP2_GMAC_CTRL_0_REG);
-	/*
-	 * Configure GIG MAC to SGMII mode connected to a fiber
-	 * transceiver
-	 */
-	val &= ~MVPP2_GMAC_PORT_TYPE_MASK;
-	writel(val, port->base + MVPP2_GMAC_CTRL_0_REG);
-
-	/* configure AN 0x9268 */
-	val = MVPP2_GMAC_EN_PCS_AN |
-		MVPP2_GMAC_AN_BYPASS_EN |
-		MVPP2_GMAC_CONFIG_MII_SPEED  |
-		MVPP2_GMAC_CONFIG_GMII_SPEED     |
-		MVPP2_GMAC_FC_ADV_EN    |
-		MVPP2_GMAC_CONFIG_FULL_DUPLEX |
-		MVPP2_GMAC_CHOOSE_SAMPLE_TX_CONFIG;
-	writel(val, port->base + MVPP2_GMAC_AUTONEG_CONFIG);
-}
-
 static void gop_gmac_sgmii_cfg(struct mvpp2_port *port)
 {
 	u32 val, thresh;
@@ -3239,9 +3195,6 @@
 	case PHY_INTERFACE_MODE_SGMII:
 		gop_gmac_sgmii_cfg(port);
 		break;
-	case PHY_INTERFACE_MODE_SGMII_2500:
-		gop_gmac_sgmii2_5_cfg(port);
-		break;
 	case PHY_INTERFACE_MODE_1000BASEX:
 		gop_gmac_1000basex_cfg(port);
 		break;
@@ -3422,7 +3375,6 @@
 		break;
 
 	case PHY_INTERFACE_MODE_SGMII:
-	case PHY_INTERFACE_MODE_SGMII_2500:
 	case PHY_INTERFACE_MODE_1000BASEX:
 	case PHY_INTERFACE_MODE_2500BASEX:
 		/* configure PCS */
@@ -3439,7 +3391,9 @@
 		gop_gmac_reset(port, 0);
 		break;
 
-	case PHY_INTERFACE_MODE_SFI:
+	case PHY_INTERFACE_MODE_10GBASER:
+	case PHY_INTERFACE_MODE_5GBASER:
+	case PHY_INTERFACE_MODE_XAUI:
 		num_of_act_lanes = 2;
 		mac_num = 0;
 		/* configure PCS */
@@ -3482,7 +3436,6 @@
 	case PHY_INTERFACE_MODE_RGMII:
 	case PHY_INTERFACE_MODE_RGMII_ID:
 	case PHY_INTERFACE_MODE_SGMII:
-	case PHY_INTERFACE_MODE_SGMII_2500:
 	case PHY_INTERFACE_MODE_1000BASEX:
 	case PHY_INTERFACE_MODE_2500BASEX:
 		if (enable)
@@ -3491,7 +3444,9 @@
 			mvpp2_port_disable(port);
 		break;
 
-	case PHY_INTERFACE_MODE_SFI:
+	case PHY_INTERFACE_MODE_10GBASER:
+	case PHY_INTERFACE_MODE_5GBASER:
+	case PHY_INTERFACE_MODE_XAUI:
 		gop_xlg_mac_port_enable(port, enable);
 
 		break;
@@ -3519,7 +3474,6 @@
 
 	if (gop_id == 2) {
 		if (phy_type == PHY_INTERFACE_MODE_SGMII ||
-		    phy_type == PHY_INTERFACE_MODE_SGMII_2500 ||
 		    phy_type == PHY_INTERFACE_MODE_1000BASEX ||
 		    phy_type == PHY_INTERFACE_MODE_2500BASEX)
 			val |= MV_NETC_GE_MAC2_SGMII;
@@ -3530,7 +3484,6 @@
 
 	if (gop_id == 3) {
 		if (phy_type == PHY_INTERFACE_MODE_SGMII ||
-		    phy_type == PHY_INTERFACE_MODE_SGMII_2500 ||
 		    phy_type == PHY_INTERFACE_MODE_1000BASEX ||
 		    phy_type == PHY_INTERFACE_MODE_2500BASEX)
 			val |= MV_NETC_GE_MAC3_SGMII;
@@ -4529,7 +4482,6 @@
 	case PHY_INTERFACE_MODE_RGMII:
 	case PHY_INTERFACE_MODE_RGMII_ID:
 	case PHY_INTERFACE_MODE_SGMII:
-	case PHY_INTERFACE_MODE_SGMII_2500:
 	case PHY_INTERFACE_MODE_1000BASEX:
 	case PHY_INTERFACE_MODE_2500BASEX:
 		mvpp2_gmac_max_rx_size_set(port);
@@ -5263,7 +5215,6 @@
 	case PHY_INTERFACE_MODE_RGMII:
 	case PHY_INTERFACE_MODE_RGMII_ID:
 	case PHY_INTERFACE_MODE_SGMII:
-	case PHY_INTERFACE_MODE_SGMII_2500:
 	case PHY_INTERFACE_MODE_1000BASEX:
 	case PHY_INTERFACE_MODE_2500BASEX:
 		mvpp2_port_power_up(port);
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 6806e3c..2415877 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -174,6 +174,11 @@
 config PHY_MARVELL
 	bool "Marvell Ethernet PHYs support"
 
+config PHY_MARVELL_10G
+	bool "Marvell Alaska 10Gbit PHYs"
+	help
+	  Support for the Marvell Alaska MV88X3310 and compatible PHYs.
+
 config PHY_MESON_GXL
 	bool "Amlogic Meson GXL Internal PHY support"
 
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index d38e99e..85d17f1 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -20,6 +20,7 @@
 obj-$(CONFIG_PHY_ET1011C) += et1011c.o
 obj-$(CONFIG_PHY_LXT) += lxt.o
 obj-$(CONFIG_PHY_MARVELL) += marvell.o
+obj-$(CONFIG_PHY_MARVELL_10G) += marvell10g.o
 obj-$(CONFIG_PHY_MICREL_KSZ8XXX) += micrel_ksz8xxx.o
 obj-$(CONFIG_PHY_MICREL_KSZ90X1) += micrel_ksz90x1.o
 obj-$(CONFIG_PHY_MESON_GXL) += meson-gxl.o
@@ -29,7 +30,7 @@
 obj-$(CONFIG_PHY_REALTEK) += realtek.o
 obj-$(CONFIG_PHY_SMSC) += smsc.o
 obj-$(CONFIG_PHY_TERANETICS) += teranetics.o
-obj-$(CONFIG_PHY_TI) += ti_phy_init.o
+obj-$(CONFIG_PHY_TI_GENERIC) += ti_phy_init.o
 obj-$(CONFIG_PHY_TI_DP83867) += dp83867.o
 obj-$(CONFIG_PHY_TI_DP83869) += dp83869.o
 obj-$(CONFIG_PHY_XILINX) += xilinx_phy.o
diff --git a/drivers/net/phy/adin.c b/drivers/net/phy/adin.c
index a5bfd96..fb9f1e4 100644
--- a/drivers/net/phy/adin.c
+++ b/drivers/net/phy/adin.c
@@ -252,7 +252,7 @@
 	return genphy_config(phydev);
 }
 
-static struct phy_driver ADIN1300_driver =  {
+U_BOOT_PHY_DRIVER(ADIN1300) = {
 	.name = "ADIN1300",
 	.uid = PHY_ID_ADIN1300,
 	.mask = 0xffffffff,
@@ -261,10 +261,3 @@
 	.startup = genphy_startup,
 	.shutdown = genphy_shutdown,
 };
-
-int phy_adin_init(void)
-{
-	phy_register(&ADIN1300_driver);
-
-	return 0;
-}
diff --git a/drivers/net/phy/aquantia.c b/drivers/net/phy/aquantia.c
index 8eb6024..a958e88 100644
--- a/drivers/net/phy/aquantia.c
+++ b/drivers/net/phy/aquantia.c
@@ -598,7 +598,7 @@
 	return 0;
 }
 
-struct phy_driver aq1202_driver = {
+U_BOOT_PHY_DRIVER(aq1202) = {
 	.name = "Aquantia AQ1202",
 	.uid = 0x3a1b445,
 	.mask = 0xfffffff0,
@@ -611,7 +611,7 @@
 	.shutdown = &gen10g_shutdown,
 };
 
-struct phy_driver aq2104_driver = {
+U_BOOT_PHY_DRIVER(aq2104) = {
 	.name = "Aquantia AQ2104",
 	.uid = 0x3a1b460,
 	.mask = 0xfffffff0,
@@ -624,7 +624,7 @@
 	.shutdown = &gen10g_shutdown,
 };
 
-struct phy_driver aqr105_driver = {
+U_BOOT_PHY_DRIVER(aqr105) = {
 	.name = "Aquantia AQR105",
 	.uid = 0x3a1b4a2,
 	.mask = 0xfffffff0,
@@ -638,7 +638,7 @@
 	.data = AQUANTIA_GEN1,
 };
 
-struct phy_driver aqr106_driver = {
+U_BOOT_PHY_DRIVER(aqr106) = {
 	.name = "Aquantia AQR106",
 	.uid = 0x3a1b4d0,
 	.mask = 0xfffffff0,
@@ -651,7 +651,7 @@
 	.shutdown = &gen10g_shutdown,
 };
 
-struct phy_driver aqr107_driver = {
+U_BOOT_PHY_DRIVER(aqr107) = {
 	.name = "Aquantia AQR107",
 	.uid = 0x3a1b4e0,
 	.mask = 0xfffffff0,
@@ -665,7 +665,7 @@
 	.data = AQUANTIA_GEN2,
 };
 
-struct phy_driver aqr112_driver = {
+U_BOOT_PHY_DRIVER(aqr112) = {
 	.name = "Aquantia AQR112",
 	.uid = 0x3a1b660,
 	.mask = 0xfffffff0,
@@ -679,7 +679,7 @@
 	.data = AQUANTIA_GEN3,
 };
 
-struct phy_driver aqr113c_driver = {
+U_BOOT_PHY_DRIVER(aqr113c) = {
 	.name = "Aquantia AQR113C",
 	.uid = 0x31c31c12,
 	.mask = 0xfffffff0,
@@ -693,7 +693,7 @@
 	.data = AQUANTIA_GEN3,
 };
 
-struct phy_driver aqr405_driver = {
+U_BOOT_PHY_DRIVER(aqr405) = {
 	.name = "Aquantia AQR405",
 	.uid = 0x3a1b4b2,
 	.mask = 0xfffffff0,
@@ -707,7 +707,7 @@
 	.data = AQUANTIA_GEN1,
 };
 
-struct phy_driver aqr412_driver = {
+U_BOOT_PHY_DRIVER(aqr412) = {
 	.name = "Aquantia AQR412",
 	.uid = 0x3a1b710,
 	.mask = 0xfffffff0,
@@ -720,18 +720,3 @@
 	.shutdown = &gen10g_shutdown,
 	.data = AQUANTIA_GEN3,
 };
-
-int phy_aquantia_init(void)
-{
-	phy_register(&aq1202_driver);
-	phy_register(&aq2104_driver);
-	phy_register(&aqr105_driver);
-	phy_register(&aqr106_driver);
-	phy_register(&aqr107_driver);
-	phy_register(&aqr112_driver);
-	phy_register(&aqr113c_driver);
-	phy_register(&aqr405_driver);
-	phy_register(&aqr412_driver);
-
-	return 0;
-}
diff --git a/drivers/net/phy/atheros.c b/drivers/net/phy/atheros.c
index c6f9f91..abb7bdf 100644
--- a/drivers/net/phy/atheros.c
+++ b/drivers/net/phy/atheros.c
@@ -333,7 +333,7 @@
 	return 0;
 }
 
-static struct phy_driver AR8021_driver =  {
+U_BOOT_PHY_DRIVER(AR8021) = {
 	.name = "AR8021",
 	.uid = AR8021_PHY_ID,
 	.mask = 0xfffffff0,
@@ -343,7 +343,7 @@
 	.shutdown = genphy_shutdown,
 };
 
-static struct phy_driver AR8031_driver =  {
+U_BOOT_PHY_DRIVER(AR8031) = {
 	.name = "AR8031/AR8033",
 	.uid = AR8031_PHY_ID,
 	.mask = 0xffffffef,
@@ -353,7 +353,7 @@
 	.shutdown = genphy_shutdown,
 };
 
-static struct phy_driver AR8035_driver =  {
+U_BOOT_PHY_DRIVER(AR8035) = {
 	.name = "AR8035",
 	.uid = AR8035_PHY_ID,
 	.mask = 0xffffffef,
@@ -362,12 +362,3 @@
 	.startup = genphy_startup,
 	.shutdown = genphy_shutdown,
 };
-
-int phy_atheros_init(void)
-{
-	phy_register(&AR8021_driver);
-	phy_register(&AR8031_driver);
-	phy_register(&AR8035_driver);
-
-	return 0;
-}
diff --git a/drivers/net/phy/b53.c b/drivers/net/phy/b53.c
index c706e2b..26e8e2f 100644
--- a/drivers/net/phy/b53.c
+++ b/drivers/net/phy/b53.c
@@ -612,7 +612,7 @@
 	return 0;
 }
 
-static struct phy_driver b53_driver = {
+U_BOOT_PHY_DRIVER(b53) = {
 	.name = "Broadcom BCM53125",
 	.uid = 0x03625c00,
 	.mask = 0xfffffc00,
@@ -623,13 +623,6 @@
 	.shutdown = &genphy_shutdown,
 };
 
-int phy_b53_init(void)
-{
-	phy_register(&b53_driver);
-
-	return 0;
-}
-
 int do_b53_reg_read(const char *name, int argc, char *const argv[])
 {
 	u8 page, offset, width;
diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
index 566fcb8..ea98cfc 100644
--- a/drivers/net/phy/broadcom.c
+++ b/drivers/net/phy/broadcom.c
@@ -323,7 +323,7 @@
 	return bcm54xx_parse_status(phydev);
 }
 
-static struct phy_driver BCM5461S_driver = {
+U_BOOT_PHY_DRIVER(bcm5461s) = {
 	.name = "Broadcom BCM5461S",
 	.uid = 0x2060c0,
 	.mask = 0xfffff0,
@@ -333,7 +333,7 @@
 	.shutdown = &genphy_shutdown,
 };
 
-static struct phy_driver BCM5464S_driver = {
+U_BOOT_PHY_DRIVER(bcm5464s) = {
 	.name = "Broadcom BCM5464S",
 	.uid = 0x2060b0,
 	.mask = 0xfffff0,
@@ -343,7 +343,7 @@
 	.shutdown = &genphy_shutdown,
 };
 
-static struct phy_driver BCM5482S_driver = {
+U_BOOT_PHY_DRIVER(bcm5482s) = {
 	.name = "Broadcom BCM5482S",
 	.uid = 0x143bcb0,
 	.mask = 0xffffff0,
@@ -353,7 +353,7 @@
 	.shutdown = &genphy_shutdown,
 };
 
-static struct phy_driver BCM_CYGNUS_driver = {
+U_BOOT_PHY_DRIVER(bcm_cygnus) = {
 	.name = "Broadcom CYGNUS GPHY",
 	.uid = 0xae025200,
 	.mask = 0xfffff0,
@@ -362,13 +362,3 @@
 	.startup = &bcm_cygnus_startup,
 	.shutdown = &genphy_shutdown,
 };
-
-int phy_broadcom_init(void)
-{
-	phy_register(&BCM5482S_driver);
-	phy_register(&BCM5464S_driver);
-	phy_register(&BCM5461S_driver);
-	phy_register(&BCM_CYGNUS_driver);
-
-	return 0;
-}
diff --git a/drivers/net/phy/ca_phy.c b/drivers/net/phy/ca_phy.c
index 16851a6..edef218 100644
--- a/drivers/net/phy/ca_phy.c
+++ b/drivers/net/phy/ca_phy.c
@@ -104,7 +104,7 @@
 }
 
 /* Support for RTL8211 External PHY */
-struct phy_driver rtl8211_external_driver = {
+U_BOOT_PHY_DRIVER(rtl8211_external) = {
 	.name = "Cortina RTL8211 External",
 	.uid = PHY_ID_RTL8211_EXT,
 	.mask = PHY_ID_MASK,
@@ -115,7 +115,7 @@
 };
 
 /* Support for RTL8211 Internal PHY */
-struct phy_driver rtl8211_internal_driver = {
+U_BOOT_PHY_DRIVER(rtl8211_internal) = {
 	.name = "Cortina RTL8211 Inrernal",
 	.uid = PHY_ID_RTL8211_INT,
 	.mask = PHY_ID_MASK,
@@ -124,10 +124,3 @@
 	.probe = &rtl8211_probe,
 	.startup = &genphy_startup,
 };
-
-int phy_cortina_access_init(void)
-{
-	phy_register(&rtl8211_external_driver);
-	phy_register(&rtl8211_internal_driver);
-	return 0;
-}
diff --git a/drivers/net/phy/cortina.c b/drivers/net/phy/cortina.c
index 778d93e..1cf8b28 100644
--- a/drivers/net/phy/cortina.c
+++ b/drivers/net/phy/cortina.c
@@ -382,7 +382,7 @@
 	return 0;
 }
 
-struct phy_driver cs4340_driver = {
+U_BOOT_PHY_DRIVER(cs4340) = {
 	.name = "Cortina CS4315/CS4340",
 	.uid = PHY_UID_CS4340,
 	.mask = 0xfffffff0,
@@ -396,7 +396,7 @@
 	.shutdown = &gen10g_shutdown,
 };
 
-struct phy_driver cs4223_driver = {
+U_BOOT_PHY_DRIVER(cs4223) = {
 	.name = "Cortina CS4223",
 	.uid = PHY_UID_CS4223,
 	.mask = 0x0ffff00f,
@@ -409,13 +409,6 @@
 	.shutdown = &gen10g_shutdown,
 };
 
-int phy_cortina_init(void)
-{
-	phy_register(&cs4340_driver);
-	phy_register(&cs4223_driver);
-	return 0;
-}
-
 int get_phy_id(struct mii_dev *bus, int addr, int devad, u32 *phy_id)
 {
 	int phy_reg;
diff --git a/drivers/net/phy/davicom.c b/drivers/net/phy/davicom.c
index 4666497..31ffa1a 100644
--- a/drivers/net/phy/davicom.c
+++ b/drivers/net/phy/davicom.c
@@ -69,7 +69,7 @@
 	return dm9161_parse_status(phydev);
 }
 
-static struct phy_driver DM9161_driver = {
+U_BOOT_PHY_DRIVER(dm9161) = {
 	.name = "Davicom DM9161E",
 	.uid = 0x181b880,
 	.mask = 0xffffff0,
@@ -78,10 +78,3 @@
 	.startup = &dm9161_startup,
 	.shutdown = &genphy_shutdown,
 };
-
-int phy_davicom_init(void)
-{
-	phy_register(&DM9161_driver);
-
-	return 0;
-}
diff --git a/drivers/net/phy/dp83867.c b/drivers/net/phy/dp83867.c
index a45152b..b861bf7 100644
--- a/drivers/net/phy/dp83867.c
+++ b/drivers/net/phy/dp83867.c
@@ -409,7 +409,7 @@
 	return 0;
 }
 
-static struct phy_driver DP83867_driver = {
+U_BOOT_PHY_DRIVER(dp83867) = {
 	.name = "TI DP83867",
 	.uid = 0x2000a231,
 	.mask = 0xfffffff0,
@@ -419,9 +419,3 @@
 	.startup = &genphy_startup,
 	.shutdown = &genphy_shutdown,
 };
-
-int phy_dp83867_init(void)
-{
-	phy_register(&DP83867_driver);
-	return 0;
-}
diff --git a/drivers/net/phy/dp83869.c b/drivers/net/phy/dp83869.c
index 23dbf42..8d32d73 100644
--- a/drivers/net/phy/dp83869.c
+++ b/drivers/net/phy/dp83869.c
@@ -473,7 +473,7 @@
 	return 0;
 }
 
-static struct phy_driver DP83869_driver = {
+U_BOOT_PHY_DRIVER(dp83869) = {
 	.name = "TI DP83869",
 	.uid = 0x2000a0f1,
 	.mask = 0xfffffff0,
@@ -485,9 +485,3 @@
 	.readext = dp83869_readext,
 	.writeext = dp83869_writeext
 };
-
-int phy_dp83869_init(void)
-{
-	phy_register(&DP83869_driver);
-	return 0;
-}
diff --git a/drivers/net/phy/et1011c.c b/drivers/net/phy/et1011c.c
index 7eff5ec..fa48314 100644
--- a/drivers/net/phy/et1011c.c
+++ b/drivers/net/phy/et1011c.c
@@ -87,7 +87,7 @@
 	return et1011c_parse_status(phydev);
 }
 
-static struct phy_driver et1011c_driver = {
+U_BOOT_PHY_DRIVER(et1011c) = {
 	.name		= "ET1011C",
 	.uid		= 0x0282f014,
 	.mask		= 0xfffffff0,
@@ -95,10 +95,3 @@
 	.config		= &et1011c_config,
 	.startup	= &et1011c_startup,
 };
-
-int phy_et1011c_init(void)
-{
-	phy_register(&et1011c_driver);
-
-	return 0;
-}
diff --git a/drivers/net/phy/fixed.c b/drivers/net/phy/fixed.c
index 1192915..2f0823b 100644
--- a/drivers/net/phy/fixed.c
+++ b/drivers/net/phy/fixed.c
@@ -93,7 +93,7 @@
 	return 0;
 }
 
-static struct phy_driver fixedphy_driver = {
+U_BOOT_PHY_DRIVER(fixedphy) = {
 	.uid		= PHY_FIXED_ID,
 	.mask		= 0xffffffff,
 	.name		= "Fixed PHY",
@@ -103,9 +103,3 @@
 	.startup	= fixedphy_startup,
 	.shutdown	= fixedphy_shutdown,
 };
-
-int phy_fixed_init(void)
-{
-	phy_register(&fixedphy_driver);
-	return 0;
-}
diff --git a/drivers/net/phy/generic_10g.c b/drivers/net/phy/generic_10g.c
index b4384e1..34ac51e 100644
--- a/drivers/net/phy/generic_10g.c
+++ b/drivers/net/phy/generic_10g.c
@@ -80,7 +80,7 @@
 	return gen10g_discover_mmds(phydev);
 }
 
-struct phy_driver gen10g_driver = {
+U_BOOT_PHY_DRIVER(gen10g) = {
 	.uid		= 0xffffffff,
 	.mask		= 0xffffffff,
 	.name		= "Generic 10G PHY",
diff --git a/drivers/net/phy/intel_xway.c b/drivers/net/phy/intel_xway.c
index dfce3f8..9d1b97d 100644
--- a/drivers/net/phy/intel_xway.c
+++ b/drivers/net/phy/intel_xway.c
@@ -30,7 +30,7 @@
 	return 0;
 }
 
-static struct phy_driver XWAY_driver = {
+U_BOOT_PHY_DRIVER(xway) = {
 	.name = "XWAY",
 	.uid = 0xD565A400,
 	.mask = 0xffffff00,
@@ -39,10 +39,3 @@
 	.startup = genphy_startup,
 	.shutdown = genphy_shutdown,
 };
-
-int phy_xway_init(void)
-{
-	phy_register(&XWAY_driver);
-
-	return 0;
-}
diff --git a/drivers/net/phy/lxt.c b/drivers/net/phy/lxt.c
index 2618deb..2094003 100644
--- a/drivers/net/phy/lxt.c
+++ b/drivers/net/phy/lxt.c
@@ -58,7 +58,7 @@
 	return lxt971_parse_status(phydev);
 }
 
-static struct phy_driver LXT971_driver = {
+U_BOOT_PHY_DRIVER(lxt971) = {
 	.name = "LXT971",
 	.uid = 0x1378e0,
 	.mask = 0xfffff0,
@@ -67,10 +67,3 @@
 	.startup = &lxt971_startup,
 	.shutdown = &genphy_shutdown,
 };
-
-int phy_lxt_init(void)
-{
-	phy_register(&LXT971_driver);
-
-	return 0;
-}
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index 1a25775..0a90f71 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -7,6 +7,7 @@
  */
 #include <common.h>
 #include <errno.h>
+#include <marvell_phy.h>
 #include <phy.h>
 #include <linux/bitops.h>
 #include <linux/delay.h>
@@ -693,90 +694,90 @@
 	return 0;
 }
 
-static struct phy_driver M88E1011S_driver = {
+U_BOOT_PHY_DRIVER(m88e1011s) = {
 	.name = "Marvell 88E1011S",
-	.uid = 0x1410c60,
-	.mask = 0xffffff0,
+	.uid = MARVELL_PHY_ID_88E1101,
+	.mask = MARVELL_PHY_ID_MASK,
 	.features = PHY_GBIT_FEATURES,
 	.config = &m88e1011s_config,
 	.startup = &m88e1011s_startup,
 	.shutdown = &genphy_shutdown,
 };
 
-static struct phy_driver M88E1111S_driver = {
+U_BOOT_PHY_DRIVER(m88e1111s) = {
 	.name = "Marvell 88E1111S",
-	.uid = 0x1410cc0,
-	.mask = 0xffffff0,
+	.uid = MARVELL_PHY_ID_88E1111,
+	.mask = MARVELL_PHY_ID_MASK,
 	.features = PHY_GBIT_FEATURES,
 	.config = &m88e1111s_config,
 	.startup = &m88e1011s_startup,
 	.shutdown = &genphy_shutdown,
 };
 
-static struct phy_driver M88E1118_driver = {
+U_BOOT_PHY_DRIVER(m88e1118) = {
 	.name = "Marvell 88E1118",
-	.uid = 0x1410e10,
-	.mask = 0xffffff0,
+	.uid = MARVELL_PHY_ID_88E1118,
+	.mask = MARVELL_PHY_ID_MASK,
 	.features = PHY_GBIT_FEATURES,
 	.config = &m88e1118_config,
 	.startup = &m88e1118_startup,
 	.shutdown = &genphy_shutdown,
 };
 
-static struct phy_driver M88E1118R_driver = {
+U_BOOT_PHY_DRIVER(m88e1118r) = {
 	.name = "Marvell 88E1118R",
-	.uid = 0x1410e40,
-	.mask = 0xffffff0,
+	.uid = MARVELL_PHY_ID_88E1116R,
+	.mask = MARVELL_PHY_ID_MASK,
 	.features = PHY_GBIT_FEATURES,
 	.config = &m88e1118_config,
 	.startup = &m88e1118_startup,
 	.shutdown = &genphy_shutdown,
 };
 
-static struct phy_driver M88E1121R_driver = {
+U_BOOT_PHY_DRIVER(m88e1121r) = {
 	.name = "Marvell 88E1121R",
-	.uid = 0x1410cb0,
-	.mask = 0xffffff0,
+	.uid = MARVELL_PHY_ID_88E1121R,
+	.mask = MARVELL_PHY_ID_MASK,
 	.features = PHY_GBIT_FEATURES,
 	.config = &m88e1121_config,
 	.startup = &genphy_startup,
 	.shutdown = &genphy_shutdown,
 };
 
-static struct phy_driver M88E1145_driver = {
+U_BOOT_PHY_DRIVER(m88e1145) = {
 	.name = "Marvell 88E1145",
-	.uid = 0x1410cd0,
-	.mask = 0xffffff0,
+	.uid = MARVELL_PHY_ID_88E1145,
+	.mask = MARVELL_PHY_ID_MASK,
 	.features = PHY_GBIT_FEATURES,
 	.config = &m88e1145_config,
 	.startup = &m88e1145_startup,
 	.shutdown = &genphy_shutdown,
 };
 
-static struct phy_driver M88E1149S_driver = {
+U_BOOT_PHY_DRIVER(m88e1149s) = {
 	.name = "Marvell 88E1149S",
-	.uid = 0x1410ca0,
-	.mask = 0xffffff0,
+	.uid = 0x01410ca0,
+	.mask = MARVELL_PHY_ID_MASK,
 	.features = PHY_GBIT_FEATURES,
 	.config = &m88e1149_config,
 	.startup = &m88e1011s_startup,
 	.shutdown = &genphy_shutdown,
 };
 
-static struct phy_driver M88E1240_driver = {
+U_BOOT_PHY_DRIVER(m88e1240) = {
 	.name = "Marvell 88E1240",
-	.uid = 0x1410e30,
-	.mask = 0xffffff0,
+	.uid = MARVELL_PHY_ID_88E1240,
+	.mask = MARVELL_PHY_ID_MASK,
 	.features = PHY_GBIT_FEATURES,
 	.config = &m88e1240_config,
 	.startup = &m88e1011s_startup,
 	.shutdown = &genphy_shutdown,
 };
 
-static struct phy_driver M88E151x_driver = {
+U_BOOT_PHY_DRIVER(m88e151x) = {
 	.name = "Marvell 88E151x",
-	.uid = 0x1410dd0,
-	.mask = 0xffffff0,
+	.uid = MARVELL_PHY_ID_88E1510,
+	.mask = MARVELL_PHY_ID_MASK,
 	.features = PHY_GBIT_FEATURES,
 	.config = &m88e151x_config,
 	.startup = &m88e1011s_startup,
@@ -785,39 +786,22 @@
 	.writeext = &m88e1xxx_phy_extwrite,
 };
 
-static struct phy_driver M88E1310_driver = {
+U_BOOT_PHY_DRIVER(m88e1310) = {
 	.name = "Marvell 88E1310",
-	.uid = 0x01410e90,
-	.mask = 0xffffff0,
+	.uid = MARVELL_PHY_ID_88E1318S,
+	.mask = MARVELL_PHY_ID_MASK,
 	.features = PHY_GBIT_FEATURES,
 	.config = &m88e1310_config,
 	.startup = &m88e1011s_startup,
 	.shutdown = &genphy_shutdown,
 };
 
-static struct phy_driver M88E1680_driver = {
+U_BOOT_PHY_DRIVER(m88e1680) = {
 	.name = "Marvell 88E1680",
-	.uid = 0x1410ed0,
-	.mask = 0xffffff0,
+	.uid = 0x01410ed0,
+	.mask = MARVELL_PHY_ID_MASK,
 	.features = PHY_GBIT_FEATURES,
 	.config = &m88e1680_config,
 	.startup = &genphy_startup,
 	.shutdown = &genphy_shutdown,
 };
-
-int phy_marvell_init(void)
-{
-	phy_register(&M88E1310_driver);
-	phy_register(&M88E1149S_driver);
-	phy_register(&M88E1145_driver);
-	phy_register(&M88E1121R_driver);
-	phy_register(&M88E1118_driver);
-	phy_register(&M88E1118R_driver);
-	phy_register(&M88E1111S_driver);
-	phy_register(&M88E1011S_driver);
-	phy_register(&M88E1240_driver);
-	phy_register(&M88E151x_driver);
-	phy_register(&M88E1680_driver);
-
-	return 0;
-}
diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c
new file mode 100644
index 0000000..9e64672
--- /dev/null
+++ b/drivers/net/phy/marvell10g.c
@@ -0,0 +1,605 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Marvell 10G 88x3310 PHY driver
+ *
+ * Based upon the ID registers, this PHY appears to be a mixture of IPs
+ * from two different companies.
+ *
+ * There appears to be several different data paths through the PHY which
+ * are automatically managed by the PHY.  The following has been determined
+ * via observation and experimentation for a setup using single-lane Serdes:
+ *
+ *       SGMII PHYXS -- BASE-T PCS -- 10G PMA -- AN -- Copper (for <= 1G)
+ *  10GBASE-KR PHYXS -- BASE-T PCS -- 10G PMA -- AN -- Copper (for 10G)
+ *  10GBASE-KR PHYXS -- BASE-R PCS -- Fiber
+ *
+ * With XAUI, observation shows:
+ *
+ *        XAUI PHYXS -- <appropriate PCS as above>
+ *
+ * and no switching of the host interface mode occurs.
+ *
+ * If both the fiber and copper ports are connected, the first to gain
+ * link takes priority and the other port is completely locked out.
+ */
+#include <common.h>
+#include <console.h>
+#include <dm/device_compat.h>
+#include <dm/devres.h>
+#include <errno.h>
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+#include <linux/compat.h>
+#include <linux/delay.h>
+#include <linux/iopoll.h>
+#include <marvell_phy.h>
+#include <phy.h>
+
+#define MV_PHY_ALASKA_NBT_QUIRK_MASK	0xfffffffe
+#define MV_PHY_ALASKA_NBT_QUIRK_REV	(MARVELL_PHY_ID_88X3310 | 0xa)
+
+#define MV_VERSION(a, b, c, d) ((a) << 24 | (b) << 16 | (c) << 8 | (d))
+
+enum {
+	MV_PMA_FW_VER0		= 0xc011,
+	MV_PMA_FW_VER1		= 0xc012,
+	MV_PMA_21X0_PORT_CTRL	= 0xc04a,
+	MV_PMA_21X0_PORT_CTRL_SWRST				= BIT(15),
+	MV_PMA_21X0_PORT_CTRL_MACTYPE_MASK			= 0x7,
+	MV_PMA_21X0_PORT_CTRL_MACTYPE_USXGMII			= 0x0,
+	MV_PMA_2180_PORT_CTRL_MACTYPE_DXGMII			= 0x1,
+	MV_PMA_2180_PORT_CTRL_MACTYPE_QXGMII			= 0x2,
+	MV_PMA_21X0_PORT_CTRL_MACTYPE_5GBASER			= 0x4,
+	MV_PMA_21X0_PORT_CTRL_MACTYPE_5GBASER_NO_SGMII_AN	= 0x5,
+	MV_PMA_21X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH	= 0x6,
+	MV_PMA_BOOT		= 0xc050,
+	MV_PMA_BOOT_FATAL	= BIT(0),
+
+	MV_PCS_BASE_T		= 0x0000,
+	MV_PCS_BASE_R		= 0x1000,
+	MV_PCS_1000BASEX	= 0x2000,
+
+	MV_PCS_CSCR1		= 0x8000,
+	MV_PCS_CSCR1_ED_MASK	= 0x0300,
+	MV_PCS_CSCR1_ED_OFF	= 0x0000,
+	MV_PCS_CSCR1_ED_RX	= 0x0200,
+	MV_PCS_CSCR1_ED_NLP	= 0x0300,
+	MV_PCS_CSCR1_MDIX_MASK	= 0x0060,
+	MV_PCS_CSCR1_MDIX_MDI	= 0x0000,
+	MV_PCS_CSCR1_MDIX_MDIX	= 0x0020,
+	MV_PCS_CSCR1_MDIX_AUTO	= 0x0060,
+
+	MV_PCS_DSC1		= 0x8003,
+	MV_PCS_DSC1_ENABLE	= BIT(9),
+	MV_PCS_DSC1_10GBT	= 0x01c0,
+	MV_PCS_DSC1_1GBR	= 0x0038,
+	MV_PCS_DSC1_100BTX	= 0x0007,
+	MV_PCS_DSC2		= 0x8004,
+	MV_PCS_DSC2_2P5G	= 0xf000,
+	MV_PCS_DSC2_5G		= 0x0f00,
+
+	MV_PCS_CSSR1		= 0x8008,
+	MV_PCS_CSSR1_SPD1_MASK	= 0xc000,
+	MV_PCS_CSSR1_SPD1_SPD2	= 0xc000,
+	MV_PCS_CSSR1_SPD1_1000	= 0x8000,
+	MV_PCS_CSSR1_SPD1_100	= 0x4000,
+	MV_PCS_CSSR1_SPD1_10	= 0x0000,
+	MV_PCS_CSSR1_DUPLEX_FULL = BIT(13),
+	MV_PCS_CSSR1_RESOLVED	= BIT(11),
+	MV_PCS_CSSR1_MDIX	= BIT(6),
+	MV_PCS_CSSR1_SPD2_MASK	= 0x000c,
+	MV_PCS_CSSR1_SPD2_5000	= 0x0008,
+	MV_PCS_CSSR1_SPD2_2500	= 0x0004,
+	MV_PCS_CSSR1_SPD2_10000	= 0x0000,
+
+	/* Temperature read register (88E2110 only) */
+	MV_PCS_TEMP		= 0x8042,
+
+	/* Number of ports on the device */
+	MV_PCS_PORT_INFO	= 0xd00d,
+	MV_PCS_PORT_INFO_NPORTS_MASK	= 0x0380,
+	MV_PCS_PORT_INFO_NPORTS_SHIFT	= 7,
+
+	/* SerDes reinitialization 88E21X0 */
+	MV_AN_21X0_SERDES_CTRL2	= 0x800f,
+	MV_AN_21X0_SERDES_CTRL2_AUTO_INIT_DIS	= BIT(13),
+	MV_AN_21X0_SERDES_CTRL2_RUN_INIT	= BIT(15),
+
+	/* These registers appear at 0x800X and 0xa00X - the 0xa00X control
+	 * registers appear to set themselves to the 0x800X when AN is
+	 * restarted, but status registers appear readable from either.
+	 */
+	MV_AN_CTRL1000		= 0x8000, /* 1000base-T control register */
+	MV_AN_STAT1000		= 0x8001, /* 1000base-T status register */
+
+	/* Vendor2 MMD registers */
+	MV_V2_PORT_CTRL		= 0xf001,
+	MV_V2_PORT_CTRL_PWRDOWN					= BIT(11),
+	MV_V2_33X0_PORT_CTRL_SWRST				= BIT(15),
+	MV_V2_33X0_PORT_CTRL_MACTYPE_MASK			= 0x7,
+	MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI			= 0x0,
+	MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH		= 0x1,
+	MV_V2_3340_PORT_CTRL_MACTYPE_RXAUI_NO_SGMII_AN		= 0x1,
+	MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI_RATE_MATCH		= 0x2,
+	MV_V2_3310_PORT_CTRL_MACTYPE_XAUI			= 0x3,
+	MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER			= 0x4,
+	MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_NO_SGMII_AN	= 0x5,
+	MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH	= 0x6,
+	MV_V2_33X0_PORT_CTRL_MACTYPE_USXGMII			= 0x7,
+	MV_V2_PORT_INTR_STS		= 0xf040,
+	MV_V2_PORT_INTR_MASK		= 0xf043,
+	MV_V2_PORT_INTR_STS_WOL_EN	= BIT(8),
+	MV_V2_MAGIC_PKT_WORD0		= 0xf06b,
+	MV_V2_MAGIC_PKT_WORD1		= 0xf06c,
+	MV_V2_MAGIC_PKT_WORD2		= 0xf06d,
+	/* Wake on LAN registers */
+	MV_V2_WOL_CTRL			= 0xf06e,
+	MV_V2_WOL_CTRL_CLEAR_STS	= BIT(15),
+	MV_V2_WOL_CTRL_MAGIC_PKT_EN	= BIT(0),
+	/* Temperature control/read registers (88X3310 only) */
+	MV_V2_TEMP_CTRL		= 0xf08a,
+	MV_V2_TEMP_CTRL_MASK	= 0xc000,
+	MV_V2_TEMP_CTRL_SAMPLE	= 0x0000,
+	MV_V2_TEMP_CTRL_DISABLE	= 0xc000,
+	MV_V2_TEMP		= 0xf08c,
+	MV_V2_TEMP_UNKNOWN	= 0x9600, /* unknown function */
+};
+
+struct mv3310_chip {
+	bool (*has_downshift)(struct phy_device *phydev);
+	int (*test_supported_interfaces)(struct phy_device *phydev);
+	int (*get_mactype)(struct phy_device *phydev);
+	int (*set_mactype)(struct phy_device *phydev, int mactype);
+	int (*select_mactype)(struct phy_device *phydev);
+	int (*init_interface)(struct phy_device *phydev, int mactype);
+};
+
+struct mv3310_priv {
+	DECLARE_BITMAP(supported_interfaces, PHY_INTERFACE_MODE_MAX);
+
+	u32 firmware_ver;
+	bool has_downshift;
+	bool rate_match;
+};
+
+static const struct mv3310_chip *to_mv3310_chip(struct phy_device *phydev)
+{
+	return (const struct mv3310_chip *)phydev->drv->data;
+}
+
+static int mv3310_power_down(struct phy_device *phydev)
+{
+	return phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
+				MV_V2_PORT_CTRL_PWRDOWN);
+}
+
+static int mv3310_power_up(struct phy_device *phydev)
+{
+	struct mv3310_priv *priv = (struct mv3310_priv *)phydev->priv;
+	int ret;
+
+	ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
+				 MV_V2_PORT_CTRL_PWRDOWN);
+
+	if (phydev->drv->uid != MARVELL_PHY_ID_88X3310 ||
+	    priv->firmware_ver < 0x00030000)
+		return ret;
+
+	return phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
+				MV_V2_33X0_PORT_CTRL_SWRST);
+}
+
+static int mv3310_reset(struct phy_device *phydev, u32 unit)
+{
+	int val, err;
+
+	err = phy_modify_mmd(phydev, MDIO_MMD_PCS, unit + MDIO_CTRL1,
+			     MDIO_CTRL1_RESET, MDIO_CTRL1_RESET);
+	if (err < 0)
+		return err;
+
+	return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_PCS,
+					 unit + MDIO_CTRL1, val,
+					 !(val & MDIO_CTRL1_RESET),
+					 5000, 100000, true);
+}
+
+static int mv3310_set_downshift(struct phy_device *phydev)
+{
+	struct mv3310_priv *priv = (struct mv3310_priv *)phydev->priv;
+	const u8 ds = 1;
+	u16 val;
+	int err;
+
+	if (!priv->has_downshift)
+		return -EOPNOTSUPP;
+
+	val = FIELD_PREP(MV_PCS_DSC2_2P5G, ds);
+	val |= FIELD_PREP(MV_PCS_DSC2_5G, ds);
+	err = phy_modify_mmd(phydev, MDIO_MMD_PCS, MV_PCS_DSC2,
+			     MV_PCS_DSC2_2P5G | MV_PCS_DSC2_5G, val);
+	if (err < 0)
+		return err;
+
+	val = MV_PCS_DSC1_ENABLE;
+	val |= FIELD_PREP(MV_PCS_DSC1_10GBT, ds);
+	val |= FIELD_PREP(MV_PCS_DSC1_1GBR, ds);
+	val |= FIELD_PREP(MV_PCS_DSC1_100BTX, ds);
+
+	return phy_modify_mmd(phydev, MDIO_MMD_PCS, MV_PCS_DSC1,
+			      MV_PCS_DSC1_ENABLE | MV_PCS_DSC1_10GBT |
+			      MV_PCS_DSC1_1GBR | MV_PCS_DSC1_100BTX, val);
+}
+
+static int mv3310_set_edpd(struct phy_device *phydev)
+{
+	int err;
+
+	err = phy_modify_mmd_changed(phydev, MDIO_MMD_PCS, MV_PCS_CSCR1,
+				     MV_PCS_CSCR1_ED_MASK,
+				     MV_PCS_CSCR1_ED_NLP);
+	if (err > 0)
+		err = mv3310_reset(phydev, MV_PCS_BASE_T);
+
+	return err;
+}
+
+static int mv3310_probe(struct phy_device *phydev)
+{
+	const struct mv3310_chip *chip = to_mv3310_chip(phydev);
+	struct mv3310_priv *priv;
+	u32 mmd_mask = MDIO_DEVS_PMAPMD | MDIO_DEVS_AN;
+	int ret;
+
+	if (!phydev->is_c45 ||
+	    (phydev->mmds & mmd_mask) != mmd_mask)
+		return -ENODEV;
+
+	ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_BOOT);
+	if (ret < 0)
+		return ret;
+
+	if (ret & MV_PMA_BOOT_FATAL) {
+		dev_warn(phydev->dev,
+			 "PHY failed to boot firmware, status=%04x\n", ret);
+		return -ENODEV;
+	}
+
+	priv = devm_kzalloc(phydev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	phydev->priv = priv;
+
+	ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_FW_VER0);
+	if (ret < 0)
+		return ret;
+
+	priv->firmware_ver = ret << 16;
+
+	ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_FW_VER1);
+	if (ret < 0)
+		return ret;
+
+	priv->firmware_ver |= ret;
+
+	dev_info(phydev->dev, "Firmware version %u.%u.%u.%u\n",
+		 priv->firmware_ver >> 24, (priv->firmware_ver >> 16) & 255,
+		 (priv->firmware_ver >> 8) & 255, priv->firmware_ver & 255);
+
+	if (chip->has_downshift)
+		priv->has_downshift = chip->has_downshift(phydev);
+
+	/* Powering down the port when not in use saves about 600mW */
+	ret = mv3310_power_down(phydev);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int mv2110_get_mactype(struct phy_device *phydev)
+{
+	int mactype;
+
+	mactype = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_21X0_PORT_CTRL);
+	if (mactype < 0)
+		return mactype;
+
+	return mactype & MV_PMA_21X0_PORT_CTRL_MACTYPE_MASK;
+}
+
+static int mv2110_set_mactype(struct phy_device *phydev, int mactype)
+{
+	int err, val;
+
+	mactype &= MV_PMA_21X0_PORT_CTRL_MACTYPE_MASK;
+	err = phy_modify_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_21X0_PORT_CTRL,
+			     MV_PMA_21X0_PORT_CTRL_SWRST |
+			     MV_PMA_21X0_PORT_CTRL_MACTYPE_MASK,
+			     MV_PMA_21X0_PORT_CTRL_SWRST | mactype);
+	if (err)
+		return err;
+
+	err = phy_set_bits_mmd(phydev, MDIO_MMD_AN, MV_AN_21X0_SERDES_CTRL2,
+			       MV_AN_21X0_SERDES_CTRL2_AUTO_INIT_DIS |
+			       MV_AN_21X0_SERDES_CTRL2_RUN_INIT);
+	if (err)
+		return err;
+
+	err = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_AN,
+					MV_AN_21X0_SERDES_CTRL2, val,
+					!(val &
+					  MV_AN_21X0_SERDES_CTRL2_RUN_INIT),
+					5000, 100000, true);
+	if (err)
+		return err;
+
+	return phy_clear_bits_mmd(phydev, MDIO_MMD_AN, MV_AN_21X0_SERDES_CTRL2,
+				  MV_AN_21X0_SERDES_CTRL2_AUTO_INIT_DIS);
+}
+
+static int mv2110_select_mactype(struct phy_device *phydev)
+{
+	if (phydev->interface == PHY_INTERFACE_MODE_USXGMII)
+		return MV_PMA_21X0_PORT_CTRL_MACTYPE_USXGMII;
+	else if (phydev->interface == PHY_INTERFACE_MODE_SGMII &&
+		 !(phydev->interface == PHY_INTERFACE_MODE_10GBASER))
+		return MV_PMA_21X0_PORT_CTRL_MACTYPE_5GBASER;
+	else if (phydev->interface == PHY_INTERFACE_MODE_10GBASER)
+		return MV_PMA_21X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH;
+	else
+		return -1;
+}
+
+static int mv3310_get_mactype(struct phy_device *phydev)
+{
+	int mactype;
+
+	mactype = phy_read_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL);
+	if (mactype < 0)
+		return mactype;
+
+	return mactype & MV_V2_33X0_PORT_CTRL_MACTYPE_MASK;
+}
+
+static int mv3310_set_mactype(struct phy_device *phydev, int mactype)
+{
+	int ret;
+
+	mactype &= MV_V2_33X0_PORT_CTRL_MACTYPE_MASK;
+	ret = phy_modify_mmd_changed(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
+				     MV_V2_33X0_PORT_CTRL_MACTYPE_MASK,
+				     mactype);
+	if (ret <= 0)
+		return ret;
+
+	return phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
+				MV_V2_33X0_PORT_CTRL_SWRST);
+}
+
+static int mv3310_select_mactype(struct phy_device *phydev)
+{
+	if (phydev->interface == PHY_INTERFACE_MODE_USXGMII)
+		return MV_V2_33X0_PORT_CTRL_MACTYPE_USXGMII;
+	else if (phydev->interface == PHY_INTERFACE_MODE_SGMII &&
+		 phydev->interface == PHY_INTERFACE_MODE_10GBASER)
+		return MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER;
+	else if (phydev->interface == PHY_INTERFACE_MODE_SGMII &&
+		 phydev->interface == PHY_INTERFACE_MODE_RXAUI)
+		return MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI;
+	else if (phydev->interface == PHY_INTERFACE_MODE_SGMII &&
+		 phydev->interface == PHY_INTERFACE_MODE_XAUI)
+		return MV_V2_3310_PORT_CTRL_MACTYPE_XAUI;
+	else if (phydev->interface == PHY_INTERFACE_MODE_10GBASER)
+		return MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH;
+	else if (phydev->interface == PHY_INTERFACE_MODE_RXAUI)
+		return MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI_RATE_MATCH;
+	else if (phydev->interface == PHY_INTERFACE_MODE_XAUI)
+		return MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH;
+	else if (phydev->interface == PHY_INTERFACE_MODE_SGMII)
+		return MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER;
+	else
+		return -1;
+}
+
+static int mv2110_init_interface(struct phy_device *phydev, int mactype)
+{
+	struct mv3310_priv *priv = (struct mv3310_priv *)phydev->priv;
+
+	priv->rate_match = false;
+
+	if (mactype == MV_PMA_21X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH)
+		priv->rate_match = true;
+
+	return 0;
+}
+
+static int mv3310_init_interface(struct phy_device *phydev, int mactype)
+{
+	struct mv3310_priv *priv = (struct mv3310_priv *)phydev->priv;
+
+	priv->rate_match = false;
+
+	if (mactype != MV_V2_3340_PORT_CTRL_MACTYPE_RXAUI_NO_SGMII_AN)
+		return 0;
+
+	if (mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH ||
+	    mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI_RATE_MATCH ||
+	    mactype == MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH)
+		priv->rate_match = true;
+
+	return 0;
+}
+
+static int mv3310_config_init(struct phy_device *phydev)
+{
+	const struct mv3310_chip *chip = to_mv3310_chip(phydev);
+	int err, mactype;
+
+	/* Check that the PHY interface type is compatible */
+	err = chip->test_supported_interfaces(phydev);
+	if (err)
+		return err;
+
+	/* Power up so reset works */
+	err = mv3310_power_up(phydev);
+	if (err)
+		return err;
+
+	/* If host provided host supported interface modes, try to select the
+	 * best one
+	 */
+	mactype = chip->select_mactype(phydev);
+	if (mactype >= 0) {
+		dev_info(phydev->dev, "Changing MACTYPE to %i\n",
+			 mactype);
+		err = chip->set_mactype(phydev, mactype);
+		if (err)
+			return err;
+	}
+
+	mactype = chip->get_mactype(phydev);
+	if (mactype < 0)
+		return mactype;
+
+	err = chip->init_interface(phydev, mactype);
+	if (err) {
+		dev_err(phydev->dev, "MACTYPE configuration invalid\n");
+		return err;
+	}
+
+	/* Enable EDPD mode - saving 600mW */
+	err = mv3310_set_edpd(phydev);
+	if (err)
+		return err;
+
+	/* Allow downshift */
+	err = mv3310_set_downshift(phydev);
+	if (err && err != -EOPNOTSUPP)
+		return err;
+
+	return 0;
+}
+
+static int mv3310_config(struct phy_device *phydev)
+{
+	int err;
+
+	err = mv3310_probe(phydev);
+	if (!err)
+		err = mv3310_config_init(phydev);
+
+	return err;
+}
+
+static int mv3310_get_number_of_ports(struct phy_device *phydev)
+{
+	int ret;
+
+	ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_PORT_INFO);
+	if (ret < 0)
+		return ret;
+
+	ret &= MV_PCS_PORT_INFO_NPORTS_MASK;
+	ret >>= MV_PCS_PORT_INFO_NPORTS_SHIFT;
+
+	return ret + 1;
+}
+
+static int mv3310_match_phy_device(struct phy_device *phydev)
+{
+	if ((phydev->phy_id & MARVELL_PHY_ID_MASK) != MARVELL_PHY_ID_88X3310)
+		return 0;
+
+	return mv3310_get_number_of_ports(phydev) == 1;
+}
+
+static int mv211x_match_phy_device(struct phy_device *phydev, bool has_5g)
+{
+	int val;
+
+	if ((phydev->phy_id & MARVELL_PHY_ID_MASK) != MARVELL_PHY_ID_88E2110)
+		return 0;
+
+	val = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_SPEED);
+	if (val < 0)
+		return val;
+
+	return !!(val & MDIO_PCS_SPEED_5G) == has_5g;
+}
+
+static int mv2110_match_phy_device(struct phy_device *phydev)
+{
+	return mv211x_match_phy_device(phydev, true);
+}
+
+static bool mv3310_has_downshift(struct phy_device *phydev)
+{
+	struct mv3310_priv *priv = (struct mv3310_priv *)phydev->priv;
+
+	/* Fails to downshift with firmware older than v0.3.5.0 */
+	return priv->firmware_ver >= MV_VERSION(0, 3, 5, 0);
+}
+
+#define mv_test_bit(iface, phydev)	\
+	({ if ((phydev)->interface & (iface)) return 0; })
+
+static int mv3310_mv3340_test_supported_interfaces(struct phy_device *phydev)
+{
+	mv_test_bit(PHY_INTERFACE_MODE_SGMII, phydev);
+	mv_test_bit(PHY_INTERFACE_MODE_2500BASEX, phydev);
+	mv_test_bit(PHY_INTERFACE_MODE_5GBASER, phydev);
+	if (mv3310_match_phy_device(phydev))
+		mv_test_bit(PHY_INTERFACE_MODE_XAUI, phydev);
+	mv_test_bit(PHY_INTERFACE_MODE_RXAUI, phydev);
+	mv_test_bit(PHY_INTERFACE_MODE_10GBASER, phydev);
+	mv_test_bit(PHY_INTERFACE_MODE_USXGMII, phydev);
+	return -ENODEV;
+}
+
+static int mv2110_mv2111_test_supported_interfaces(struct phy_device *phydev)
+{
+	mv_test_bit(PHY_INTERFACE_MODE_SGMII, phydev);
+	mv_test_bit(PHY_INTERFACE_MODE_2500BASEX, phydev);
+	if (mv2110_match_phy_device(phydev))
+		mv_test_bit(PHY_INTERFACE_MODE_5GBASER, phydev);
+	mv_test_bit(PHY_INTERFACE_MODE_10GBASER, phydev);
+	mv_test_bit(PHY_INTERFACE_MODE_USXGMII, phydev);
+	return -ENODEV;
+}
+
+static const struct mv3310_chip mv3310_mv3340_type = {
+	.has_downshift = mv3310_has_downshift,
+	.test_supported_interfaces = mv3310_mv3340_test_supported_interfaces,
+	.get_mactype = mv3310_get_mactype,
+	.set_mactype = mv3310_set_mactype,
+	.select_mactype = mv3310_select_mactype,
+	.init_interface = mv3310_init_interface,
+};
+
+static const struct mv3310_chip mv2110_mv2111_type = {
+	.test_supported_interfaces = mv2110_mv2111_test_supported_interfaces,
+	.get_mactype = mv2110_get_mactype,
+	.set_mactype = mv2110_set_mactype,
+	.select_mactype = mv2110_select_mactype,
+	.init_interface = mv2110_init_interface,
+};
+
+U_BOOT_PHY_DRIVER(mv88e3310_mv88e3340) = {
+	.name		= "mv88x3310",
+	.uid		= MARVELL_PHY_ID_88X3310,
+	.mask		= MARVELL_PHY_ID_MASK,
+	.features	= PHY_10G_FEATURES,
+	.data		= (ulong)&mv3310_mv3340_type,
+	.config		= mv3310_config,
+};
+
+U_BOOT_PHY_DRIVER(mv88e2110_mv88e2111) = {
+	.name		= "mv88e2110",
+	.uid		= MARVELL_PHY_ID_88E2110,
+	.mask		= MARVELL_PHY_ID_MASK,
+	.features	= PHY_10G_FEATURES,
+	.data		= (ulong)&mv2110_mv2111_type,
+	.config		= mv3310_config,
+};
diff --git a/drivers/net/phy/meson-gxl.c b/drivers/net/phy/meson-gxl.c
index 753ca72..b49c9b5 100644
--- a/drivers/net/phy/meson-gxl.c
+++ b/drivers/net/phy/meson-gxl.c
@@ -124,7 +124,7 @@
 	return genphy_config(phydev);
 }
 
-static struct phy_driver meson_gxl_phy_driver = {
+U_BOOT_PHY_DRIVER(meson_gxl_phy) = {
 	.name = "Meson GXL Internal PHY",
 	.uid = 0x01814400,
 	.mask = 0xfffffff0,
@@ -133,10 +133,3 @@
 	.startup = &meson_gxl_startup,
 	.shutdown = &genphy_shutdown,
 };
-
-int phy_meson_gxl_init(void)
-{
-	phy_register(&meson_gxl_phy_driver);
-
-	return 0;
-}
diff --git a/drivers/net/phy/micrel_ksz8xxx.c b/drivers/net/phy/micrel_ksz8xxx.c
index 60d42fe..b0f3abc 100644
--- a/drivers/net/phy/micrel_ksz8xxx.c
+++ b/drivers/net/phy/micrel_ksz8xxx.c
@@ -14,7 +14,7 @@
 #include <phy.h>
 #include <linux/bitops.h>
 
-static struct phy_driver KSZ804_driver = {
+U_BOOT_PHY_DRIVER(ksz804) = {
 	.name = "Micrel KSZ804",
 	.uid = 0x221510,
 	.mask = 0xfffff0,
@@ -44,7 +44,7 @@
 	return genphy_config(phydev);
 }
 
-static struct phy_driver KSZ8031_driver = {
+U_BOOT_PHY_DRIVER(ksz8031) = {
 	.name = "Micrel KSZ8021/KSZ8031",
 	.uid = 0x221550,
 	.mask = 0xfffff0,
@@ -72,7 +72,7 @@
 	return genphy_config(phydev);
 }
 
-static struct phy_driver KSZ8051_driver = {
+U_BOOT_PHY_DRIVER(ksz8051) = {
 	.name = "Micrel KSZ8051",
 	.uid = 0x221550,
 	.mask = 0xfffff0,
@@ -87,7 +87,7 @@
 	return phy_write(phydev, MDIO_MMD_PMAPMD, MDIO_DEVID1, 0xB61A);
 }
 
-static struct phy_driver KSZ8061_driver = {
+U_BOOT_PHY_DRIVER(ksz8061) = {
 	.name = "Micrel KSZ8061",
 	.uid = 0x00221570,
 	.mask = 0xfffff0,
@@ -115,7 +115,7 @@
 	return genphy_config(phydev);
 }
 
-static struct phy_driver KSZ8081_driver = {
+U_BOOT_PHY_DRIVER(ksz8081) = {
 	.name = "Micrel KSZ8081",
 	.uid = 0x221560,
 	.mask = 0xfffff0,
@@ -172,7 +172,7 @@
 	return 0;
 }
 
-static struct phy_driver ksz8895_driver = {
+U_BOOT_PHY_DRIVER(ksz8895) = {
 	.name = "Micrel KSZ8895/KSZ8864",
 	.uid  = 0x221450,
 	.mask = 0xffffe1,
@@ -185,7 +185,7 @@
 /* Micrel used the exact same model number for the KSZ9021,
  * so the revision number is used to distinguish them.
  */
-static struct phy_driver KS8721_driver = {
+U_BOOT_PHY_DRIVER(ks8721) = {
 	.name = "Micrel KS8721BL",
 	.uid = 0x221618,
 	.mask = 0xfffffc,
@@ -210,7 +210,7 @@
 	return 0;
 }
 
-static struct phy_driver ksz886x_driver = {
+U_BOOT_PHY_DRIVER(ksz886x) = {
 	.name = "Micrel KSZ886x Switch",
 	.uid  = 0x00221430,
 	.mask = 0xfffff0,
@@ -219,16 +219,3 @@
 	.startup = &ksz886x_startup,
 	.shutdown = &genphy_shutdown,
 };
-
-int phy_micrel_ksz8xxx_init(void)
-{
-	phy_register(&KSZ804_driver);
-	phy_register(&KSZ8031_driver);
-	phy_register(&KSZ8051_driver);
-	phy_register(&KSZ8061_driver);
-	phy_register(&KSZ8081_driver);
-	phy_register(&KS8721_driver);
-	phy_register(&ksz8895_driver);
-	phy_register(&ksz886x_driver);
-	return 0;
-}
diff --git a/drivers/net/phy/micrel_ksz90x1.c b/drivers/net/phy/micrel_ksz90x1.c
index 79ebdb5..ffc3c98 100644
--- a/drivers/net/phy/micrel_ksz90x1.c
+++ b/drivers/net/phy/micrel_ksz90x1.c
@@ -270,7 +270,7 @@
 	return 0;
 }
 
-static struct phy_driver ksz9021_driver = {
+U_BOOT_PHY_DRIVER(ksz9021) = {
 	.name = "Micrel ksz9021",
 	.uid  = 0x221610,
 	.mask = 0xfffffe,
@@ -368,7 +368,7 @@
 	return genphy_config(phydev);
 }
 
-static struct phy_driver ksz9031_driver = {
+U_BOOT_PHY_DRIVER(ksz9031) = {
 	.name = "Micrel ksz9031",
 	.uid  = PHY_ID_KSZ9031,
 	.mask = MII_KSZ9x31_SILICON_REV_MASK,
@@ -477,7 +477,7 @@
 	return genphy_config(phydev);
 }
 
-static struct phy_driver ksz9131_driver = {
+U_BOOT_PHY_DRIVER(ksz9131) = {
 	.name = "Micrel ksz9131",
 	.uid  = PHY_ID_KSZ9131,
 	.mask = MII_KSZ9x31_SILICON_REV_MASK,
@@ -497,11 +497,3 @@
 
 	return phyid;
 }
-
-int phy_micrel_ksz90x1_init(void)
-{
-	phy_register(&ksz9021_driver);
-	phy_register(&ksz9031_driver);
-	phy_register(&ksz9131_driver);
-	return 0;
-}
diff --git a/drivers/net/phy/mscc.c b/drivers/net/phy/mscc.c
index f9482b2..ef1761a 100644
--- a/drivers/net/phy/mscc.c
+++ b/drivers/net/phy/mscc.c
@@ -1558,7 +1558,7 @@
 	return 0;
 }
 
-static struct phy_driver VSC8530_driver = {
+U_BOOT_PHY_DRIVER(vsc8530) = {
 	.name = "Microsemi VSC8530",
 	.uid = PHY_ID_VSC8530,
 	.mask = 0x000ffff0,
@@ -1568,7 +1568,7 @@
 	.shutdown = &genphy_shutdown,
 };
 
-static struct phy_driver VSC8531_driver = {
+U_BOOT_PHY_DRIVER(vsc8531) = {
 	.name = "Microsemi VSC8531",
 	.uid = PHY_ID_VSC8531,
 	.mask = 0x000ffff0,
@@ -1578,7 +1578,7 @@
 	.shutdown = &genphy_shutdown,
 };
 
-static struct phy_driver VSC8502_driver = {
+U_BOOT_PHY_DRIVER(vsc8502) = {
 	.name = "Microsemi VSC8502",
 	.uid = PHY_ID_VSC8502,
 	.mask = 0x000ffff0,
@@ -1588,7 +1588,7 @@
 	.shutdown = &genphy_shutdown,
 };
 
-static struct phy_driver VSC8540_driver = {
+U_BOOT_PHY_DRIVER(vsc8540) = {
 	.name = "Microsemi VSC8540",
 	.uid = PHY_ID_VSC8540,
 	.mask = 0x000ffff0,
@@ -1598,7 +1598,7 @@
 	.shutdown = &genphy_shutdown,
 };
 
-static struct phy_driver VSC8541_driver = {
+U_BOOT_PHY_DRIVER(vsc8541) = {
 	.name = "Microsemi VSC8541",
 	.uid = PHY_ID_VSC8541,
 	.mask = 0x000ffff0,
@@ -1608,7 +1608,7 @@
 	.shutdown = &genphy_shutdown,
 };
 
-static struct phy_driver VSC8574_driver = {
+U_BOOT_PHY_DRIVER(vsc8574) = {
 	.name = "Microsemi VSC8574",
 	.uid = PHY_ID_VSC8574,
 	.mask = 0x000ffff0,
@@ -1618,7 +1618,7 @@
 	.shutdown = &genphy_shutdown,
 };
 
-static struct phy_driver VSC8584_driver = {
+U_BOOT_PHY_DRIVER(vsc8584) = {
 	.name = "Microsemi VSC8584",
 	.uid = PHY_ID_VSC8584,
 	.mask = 0x000ffff0,
@@ -1627,16 +1627,3 @@
 	.startup = &mscc_startup,
 	.shutdown = &genphy_shutdown,
 };
-
-int phy_mscc_init(void)
-{
-	phy_register(&VSC8530_driver);
-	phy_register(&VSC8531_driver);
-	phy_register(&VSC8502_driver);
-	phy_register(&VSC8540_driver);
-	phy_register(&VSC8541_driver);
-	phy_register(&VSC8574_driver);
-	phy_register(&VSC8584_driver);
-
-	return 0;
-}
diff --git a/drivers/net/phy/mv88e61xx.c b/drivers/net/phy/mv88e61xx.c
index 7ab6016..8577810 100644
--- a/drivers/net/phy/mv88e61xx.c
+++ b/drivers/net/phy/mv88e61xx.c
@@ -1127,7 +1127,7 @@
 	return 0;
 }
 
-static struct phy_driver mv88e61xx_driver = {
+U_BOOT_PHY_DRIVER(mv88e61xx) = {
 	.name = "Marvell MV88E61xx",
 	.uid = 0x01410eb1,
 	.mask = 0xfffffff0,
@@ -1138,7 +1138,7 @@
 	.shutdown = &genphy_shutdown,
 };
 
-static struct phy_driver mv88e609x_driver = {
+U_BOOT_PHY_DRIVER(mv88e609x) = {
 	.name = "Marvell MV88E609x",
 	.uid = 0x1410c89,
 	.mask = 0xfffffff0,
@@ -1149,7 +1149,7 @@
 	.shutdown = &genphy_shutdown,
 };
 
-static struct phy_driver mv88e6071_driver = {
+U_BOOT_PHY_DRIVER(mv88e6071) = {
 	.name = "Marvell MV88E6071",
 	.uid = 0x1410db0,
 	.mask = 0xfffffff0,
@@ -1160,15 +1160,6 @@
 	.shutdown = &genphy_shutdown,
 };
 
-int phy_mv88e61xx_init(void)
-{
-	phy_register(&mv88e61xx_driver);
-	phy_register(&mv88e609x_driver);
-	phy_register(&mv88e6071_driver);
-
-	return 0;
-}
-
 /*
  * Overload weak get_phy_id definition since we need non-standard functions
  * to read PHY registers
diff --git a/drivers/net/phy/natsemi.c b/drivers/net/phy/natsemi.c
index efde457..6b9e99e 100644
--- a/drivers/net/phy/natsemi.c
+++ b/drivers/net/phy/natsemi.c
@@ -33,7 +33,7 @@
 	return 0;
 }
 
-static struct phy_driver DP83630_driver = {
+U_BOOT_PHY_DRIVER(dp83630) = {
 	.name = "NatSemi DP83630",
 	.uid = 0x20005ce1,
 	.mask = 0xfffffff0,
@@ -103,7 +103,7 @@
 }
 
 
-static struct phy_driver DP83865_driver = {
+U_BOOT_PHY_DRIVER(dp83865) = {
 	.name = "NatSemi DP83865",
 	.uid = 0x20005c70,
 	.mask = 0xfffffff0,
@@ -146,7 +146,7 @@
 	return dp83848_parse_status(phydev);
 }
 
-static struct phy_driver DP83848_driver = {
+U_BOOT_PHY_DRIVER(dp83848) = {
 	.name = "NatSemi DP83848",
 	.uid = 0x20005c90,
 	.mask = 0x2000ff90,
@@ -155,12 +155,3 @@
 	.startup = &dp83848_startup,
 	.shutdown = &genphy_shutdown,
 };
-
-int phy_natsemi_init(void)
-{
-	phy_register(&DP83630_driver);
-	phy_register(&DP83865_driver);
-	phy_register(&DP83848_driver);
-
-	return 0;
-}
diff --git a/drivers/net/phy/ncsi.c b/drivers/net/phy/ncsi.c
index bb7eceb..eb3fd65 100644
--- a/drivers/net/phy/ncsi.c
+++ b/drivers/net/phy/ncsi.c
@@ -881,7 +881,7 @@
 	return 0;
 }
 
-static struct phy_driver ncsi_driver = {
+U_BOOT_PHY_DRIVER(ncsi) = {
 	.uid		= PHY_NCSI_ID,
 	.mask		= 0xffffffff,
 	.name		= "NC-SI",
@@ -891,9 +891,3 @@
 	.startup	= ncsi_startup,
 	.shutdown	= ncsi_shutdown,
 };
-
-int phy_ncsi_init(void)
-{
-	phy_register(&ncsi_driver);
-	return 0;
-}
diff --git a/drivers/net/phy/nxp-c45-tja11xx.c b/drivers/net/phy/nxp-c45-tja11xx.c
index a0f41fa..f701790 100644
--- a/drivers/net/phy/nxp-c45-tja11xx.c
+++ b/drivers/net/phy/nxp-c45-tja11xx.c
@@ -330,7 +330,7 @@
 	return 0;
 }
 
-static struct phy_driver nxp_c45_tja11xx = {
+U_BOOT_PHY_DRIVER(nxp_c45_tja11xx) = {
 	.name = "NXP C45 TJA1103",
 	.uid  = PHY_ID_TJA_1103,
 	.mask = 0xfffff0,
@@ -340,9 +340,3 @@
 	.startup = &nxp_c45_startup,
 	.shutdown = &genphy_shutdown,
 };
-
-int phy_nxp_c45_tja11xx_init(void)
-{
-	phy_register(&nxp_c45_tja11xx);
-	return 0;
-}
diff --git a/drivers/net/phy/nxp-tja11xx.c b/drivers/net/phy/nxp-tja11xx.c
index 30dec5e..471b0e3 100644
--- a/drivers/net/phy/nxp-tja11xx.c
+++ b/drivers/net/phy/nxp-tja11xx.c
@@ -248,7 +248,7 @@
 	return 0;
 }
 
-static struct phy_driver TJA1100_driver = {
+U_BOOT_PHY_DRIVER(tja1100) = {
 	.name = "NXP TJA1100",
 	.uid = PHY_ID_TJA1100,
 	.mask = PHY_ID_MASK,
@@ -258,7 +258,7 @@
 	.shutdown = &genphy_shutdown,
 };
 
-static struct phy_driver TJA1101_driver = {
+U_BOOT_PHY_DRIVER(tja1101) = {
 	.name = "NXP TJA1101",
 	.uid = PHY_ID_TJA1101,
 	.mask = PHY_ID_MASK,
@@ -267,11 +267,3 @@
 	.startup = &tja11xx_startup,
 	.shutdown = &genphy_shutdown,
 };
-
-int phy_nxp_tja11xx_init(void)
-{
-	phy_register(&TJA1100_driver);
-	phy_register(&TJA1101_driver);
-
-	return 0;
-}
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 80230b9..0eeb0cb 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -451,7 +451,7 @@
 	return 0;
 }
 
-static struct phy_driver genphy_driver = {
+U_BOOT_PHY_DRIVER(genphy) = {
 	.uid		= 0xffffffff,
 	.mask		= 0xffffffff,
 	.name		= "Generic PHY",
@@ -463,144 +463,36 @@
 	.shutdown	= genphy_shutdown,
 };
 
-static int genphy_init(void)
-{
-	return phy_register(&genphy_driver);
-}
-
-static LIST_HEAD(phy_drivers);
-
+#ifdef CONFIG_NEEDS_MANUAL_RELOC
 int phy_init(void)
 {
-#ifdef CONFIG_NEEDS_MANUAL_RELOC
-	/*
-	 * The pointers inside phy_drivers also needs to be updated incase of
-	 * manual reloc, without which these points to some invalid
-	 * pre reloc address and leads to invalid accesses, hangs.
-	 */
-	struct list_head *head = &phy_drivers;
+	const int ll_n_ents = ll_entry_count(struct phy_driver, phy_driver);
+	struct phy_driver *drv, *ll_entry;
 
-	head->next = (void *)head->next + gd->reloc_off;
-	head->prev = (void *)head->prev + gd->reloc_off;
-#endif
-
-#ifdef CONFIG_B53_SWITCH
-	phy_b53_init();
-#endif
-#ifdef CONFIG_MV88E61XX_SWITCH
-	phy_mv88e61xx_init();
-#endif
-#ifdef CONFIG_PHY_ADIN
-	phy_adin_init();
-#endif
-#ifdef CONFIG_PHY_AQUANTIA
-	phy_aquantia_init();
-#endif
-#ifdef CONFIG_PHY_ATHEROS
-	phy_atheros_init();
-#endif
-#ifdef CONFIG_PHY_BROADCOM
-	phy_broadcom_init();
-#endif
-#ifdef CONFIG_PHY_CORTINA
-	phy_cortina_init();
-#endif
-#ifdef CONFIG_PHY_CORTINA_ACCESS
-	phy_cortina_access_init();
-#endif
-#ifdef CONFIG_PHY_DAVICOM
-	phy_davicom_init();
-#endif
-#ifdef CONFIG_PHY_ET1011C
-	phy_et1011c_init();
-#endif
-#ifdef CONFIG_PHY_LXT
-	phy_lxt_init();
-#endif
-#ifdef CONFIG_PHY_MARVELL
-	phy_marvell_init();
-#endif
-#ifdef CONFIG_PHY_MICREL_KSZ8XXX
-	phy_micrel_ksz8xxx_init();
-#endif
-#ifdef CONFIG_PHY_MICREL_KSZ90X1
-	phy_micrel_ksz90x1_init();
-#endif
-#ifdef CONFIG_PHY_MESON_GXL
-	phy_meson_gxl_init();
-#endif
-#ifdef CONFIG_PHY_NATSEMI
-	phy_natsemi_init();
-#endif
-#ifdef CONFIG_NXP_C45_TJA11XX_PHY
-	phy_nxp_c45_tja11xx_init();
-#endif
-#ifdef CONFIG_PHY_NXP_TJA11XX
-	phy_nxp_tja11xx_init();
-#endif
-#ifdef CONFIG_PHY_REALTEK
-	phy_realtek_init();
-#endif
-#ifdef CONFIG_PHY_SMSC
-	phy_smsc_init();
-#endif
-#ifdef CONFIG_PHY_TERANETICS
-	phy_teranetics_init();
-#endif
-#ifdef CONFIG_PHY_TI
-	phy_ti_init();
-#endif
-#ifdef CONFIG_PHY_VITESSE
-	phy_vitesse_init();
-#endif
-#ifdef CONFIG_PHY_XILINX
-	phy_xilinx_init();
-#endif
-#ifdef CONFIG_PHY_XWAY
-	phy_xway_init();
-#endif
-#ifdef CONFIG_PHY_MSCC
-	phy_mscc_init();
-#endif
-#ifdef CONFIG_PHY_FIXED
-	phy_fixed_init();
-#endif
-#ifdef CONFIG_PHY_NCSI
-	phy_ncsi_init();
-#endif
-#ifdef CONFIG_PHY_XILINX_GMII2RGMII
-	phy_xilinx_gmii2rgmii_init();
-#endif
-	genphy_init();
+	/* Perform manual relocation on linker list based PHY drivers */
+	ll_entry = ll_entry_start(struct phy_driver, phy_driver);
+	for (drv = ll_entry; drv != ll_entry + ll_n_ents; drv++) {
+		if (drv->probe)
+			drv->probe += gd->reloc_off;
+		if (drv->config)
+			drv->config += gd->reloc_off;
+		if (drv->startup)
+			drv->startup += gd->reloc_off;
+		if (drv->shutdown)
+			drv->shutdown += gd->reloc_off;
+		if (drv->readext)
+			drv->readext += gd->reloc_off;
+		if (drv->writeext)
+			drv->writeext += gd->reloc_off;
+		if (drv->read_mmd)
+			drv->read_mmd += gd->reloc_off;
+		if (drv->write_mmd)
+			drv->write_mmd += gd->reloc_off;
+	}
 
 	return 0;
 }
-
-int phy_register(struct phy_driver *drv)
-{
-	INIT_LIST_HEAD(&drv->list);
-	list_add_tail(&drv->list, &phy_drivers);
-
-#ifdef CONFIG_NEEDS_MANUAL_RELOC
-	if (drv->probe)
-		drv->probe += gd->reloc_off;
-	if (drv->config)
-		drv->config += gd->reloc_off;
-	if (drv->startup)
-		drv->startup += gd->reloc_off;
-	if (drv->shutdown)
-		drv->shutdown += gd->reloc_off;
-	if (drv->readext)
-		drv->readext += gd->reloc_off;
-	if (drv->writeext)
-		drv->writeext += gd->reloc_off;
-	if (drv->read_mmd)
-		drv->read_mmd += gd->reloc_off;
-	if (drv->write_mmd)
-		drv->write_mmd += gd->reloc_off;
 #endif
-	return 0;
-}
 
 int phy_set_supported(struct phy_device *phydev, u32 max_speed)
 {
@@ -645,23 +537,23 @@
 {
 #ifdef CONFIG_PHYLIB_10G
 	if (phydev->is_c45)
-		return &gen10g_driver;
+		return ll_entry_get(struct phy_driver, gen10g, phy_driver);
 #endif
 
-	return &genphy_driver;
+	return ll_entry_get(struct phy_driver, genphy, phy_driver);
 }
 
 static struct phy_driver *get_phy_driver(struct phy_device *phydev)
 {
-	struct list_head *entry;
+	const int ll_n_ents = ll_entry_count(struct phy_driver, phy_driver);
 	int phy_id = phydev->phy_id;
-	struct phy_driver *drv = NULL;
+	struct phy_driver *ll_entry;
+	struct phy_driver *drv;
 
-	list_for_each(entry, &phy_drivers) {
-		drv = list_entry(entry, struct phy_driver, list);
+	ll_entry = ll_entry_start(struct phy_driver, phy_driver);
+	for (drv = ll_entry; drv != ll_entry + ll_n_ents; drv++)
 		if ((drv->uid & drv->mask) == (phy_id & drv->mask))
 			return drv;
-	}
 
 	/* If we made it here, there's no driver for this PHY */
 	return generic_for_phy(phydev);
@@ -1266,9 +1158,67 @@
 	return 0;
 }
 
+/**
+ * phy_modify_mmd_changed - Function for modifying a register on MMD
+ * @phydev: the phy_device struct
+ * @devad: the MMD containing register to modify
+ * @regnum: register number to modify
+ * @mask: bit mask of bits to clear
+ * @set: new value of bits set in mask to write to @regnum
+ *
+ * NOTE: MUST NOT be called from interrupt context,
+ * because the bus read/write functions may wait for an interrupt
+ * to conclude the operation.
+ *
+ * Returns negative errno, 0 if there was no change, and 1 in case of change
+ */
+int phy_modify_mmd_changed(struct phy_device *phydev, int devad, u32 regnum,
+			   u16 mask, u16 set)
+{
+	int new, ret;
+
+	ret = phy_read_mmd(phydev, devad, regnum);
+	if (ret < 0)
+		return ret;
+
+	new = (ret & ~mask) | set;
+	if (new == ret)
+		return 0;
+
+	ret = phy_write_mmd(phydev, devad, regnum, new);
+
+	return ret < 0 ? ret : 1;
+}
+
+/**
+ * phy_modify_mmd - Convenience function for modifying a register on MMD
+ * @phydev: the phy_device struct
+ * @devad: the MMD containing register to modify
+ * @regnum: register number to modify
+ * @mask: bit mask of bits to clear
+ * @set: new value of bits set in mask to write to @regnum
+ *
+ * NOTE: MUST NOT be called from interrupt context,
+ * because the bus read/write functions may wait for an interrupt
+ * to conclude the operation.
+ */
+int phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum,
+		   u16 mask, u16 set)
+{
+	int ret;
+
+	ret = phy_modify_mmd_changed(phydev, devad, regnum, mask, set);
+
+	return ret < 0 ? ret : 0;
+}
+
 bool phy_interface_is_ncsi(void)
 {
+#ifdef CONFIG_PHY_NCSI
 	struct eth_pdata *pdata = dev_get_plat(eth_get_dev());
 
 	return pdata->phy_interface == PHY_INTERFACE_MODE_NCSI;
+#else
+	return 0;
+#endif
 }
diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
index 24c3ea5..247d975 100644
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -409,7 +409,7 @@
 }
 
 /* Support for RTL8211B PHY */
-static struct phy_driver RTL8211B_driver = {
+U_BOOT_PHY_DRIVER(rtl8211b) = {
 	.name = "RealTek RTL8211B",
 	.uid = 0x1cc912,
 	.mask = 0xffffff,
@@ -421,7 +421,7 @@
 };
 
 /* Support for RTL8211E-VB-CG, RTL8211E-VL-CG and RTL8211EG-VB-CG PHYs */
-static struct phy_driver RTL8211E_driver = {
+U_BOOT_PHY_DRIVER(rtl8211e) = {
 	.name = "RealTek RTL8211E",
 	.uid = 0x1cc915,
 	.mask = 0xffffff,
@@ -433,7 +433,7 @@
 };
 
 /* Support for RTL8211DN PHY */
-static struct phy_driver RTL8211DN_driver = {
+U_BOOT_PHY_DRIVER(rtl8211dn) = {
 	.name = "RealTek RTL8211DN",
 	.uid = 0x1cc914,
 	.mask = 0xffffff,
@@ -444,7 +444,7 @@
 };
 
 /* Support for RTL8211F PHY */
-static struct phy_driver RTL8211F_driver = {
+U_BOOT_PHY_DRIVER(rtl8211f) = {
 	.name = "RealTek RTL8211F",
 	.uid = 0x1cc916,
 	.mask = 0xffffff,
@@ -458,7 +458,7 @@
 };
 
 /* Support for RTL8201F PHY */
-static struct phy_driver RTL8201F_driver = {
+U_BOOT_PHY_DRIVER(rtl8201f) = {
 	.name = "RealTek RTL8201F 10/100Mbps Ethernet",
 	.uid = 0x1cc816,
 	.mask = 0xffffff,
@@ -468,14 +468,3 @@
 	.startup = &rtl8211e_startup,
 	.shutdown = &genphy_shutdown,
 };
-
-int phy_realtek_init(void)
-{
-	phy_register(&RTL8211B_driver);
-	phy_register(&RTL8211E_driver);
-	phy_register(&RTL8211F_driver);
-	phy_register(&RTL8211DN_driver);
-	phy_register(&RTL8201F_driver);
-
-	return 0;
-}
diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c
index 7740a25..056b607 100644
--- a/drivers/net/phy/smsc.c
+++ b/drivers/net/phy/smsc.c
@@ -43,7 +43,7 @@
 	return smsc_parse_status(phydev);
 }
 
-static struct phy_driver lan8700_driver = {
+U_BOOT_PHY_DRIVER(lan8700) = {
 	.name = "SMSC LAN8700",
 	.uid = 0x0007c0c0,
 	.mask = 0xffff0,
@@ -53,7 +53,7 @@
 	.shutdown = &genphy_shutdown,
 };
 
-static struct phy_driver lan911x_driver = {
+U_BOOT_PHY_DRIVER(lan911x) = {
 	.name = "SMSC LAN911x Internal PHY",
 	.uid = 0x0007c0d0,
 	.mask = 0xffff0,
@@ -63,7 +63,7 @@
 	.shutdown = &genphy_shutdown,
 };
 
-static struct phy_driver lan8710_driver = {
+U_BOOT_PHY_DRIVER(lan8710) = {
 	.name = "SMSC LAN8710/LAN8720",
 	.uid = 0x0007c0f0,
 	.mask = 0xffff0,
@@ -73,7 +73,7 @@
 	.shutdown = &genphy_shutdown,
 };
 
-static struct phy_driver lan8740_driver = {
+U_BOOT_PHY_DRIVER(lan8740) = {
 	.name = "SMSC LAN8740",
 	.uid = 0x0007c110,
 	.mask = 0xffff0,
@@ -83,7 +83,7 @@
 	.shutdown = &genphy_shutdown,
 };
 
-static struct phy_driver lan8741_driver = {
+U_BOOT_PHY_DRIVER(lan8741) = {
 	.name = "SMSC LAN8741",
 	.uid = 0x0007c120,
 	.mask = 0xffff0,
@@ -93,7 +93,7 @@
 	.shutdown = &genphy_shutdown,
 };
 
-static struct phy_driver lan8742_driver = {
+U_BOOT_PHY_DRIVER(lan8742) = {
 	.name = "SMSC LAN8742",
 	.uid = 0x0007c130,
 	.mask = 0xffff0,
@@ -102,15 +102,3 @@
 	.startup = &genphy_startup,
 	.shutdown = &genphy_shutdown,
 };
-
-int phy_smsc_init(void)
-{
-	phy_register(&lan8710_driver);
-	phy_register(&lan911x_driver);
-	phy_register(&lan8700_driver);
-	phy_register(&lan8740_driver);
-	phy_register(&lan8741_driver);
-	phy_register(&lan8742_driver);
-
-	return 0;
-}
diff --git a/drivers/net/phy/teranetics.c b/drivers/net/phy/teranetics.c
index 60049c2..15f2c12 100644
--- a/drivers/net/phy/teranetics.c
+++ b/drivers/net/phy/teranetics.c
@@ -90,7 +90,7 @@
 	return 0;
 }
 
-struct phy_driver tn2020_driver = {
+U_BOOT_PHY_DRIVER(tn2020) = {
 	.name = "Teranetics TN2020",
 	.uid = PHY_UID_TN2020,
 	.mask = 0xfffffff0,
@@ -102,10 +102,3 @@
 	.startup = &tn2020_startup,
 	.shutdown = &gen10g_shutdown,
 };
-
-int phy_teranetics_init(void)
-{
-	phy_register(&tn2020_driver);
-
-	return 0;
-}
diff --git a/drivers/net/phy/ti_phy_init.c b/drivers/net/phy/ti_phy_init.c
index 075b19a..a087819 100644
--- a/drivers/net/phy/ti_phy_init.c
+++ b/drivers/net/phy/ti_phy_init.c
@@ -10,8 +10,7 @@
 #include <phy.h>
 #include "ti_phy_init.h"
 
-#ifdef CONFIG_PHY_TI_GENERIC
-static struct phy_driver dp83822_driver = {
+U_BOOT_PHY_DRIVER(dp83822) = {
 	.name = "TI DP83822",
 	.uid = 0x2000a240,
 	.mask = 0xfffffff0,
@@ -21,7 +20,7 @@
 	.shutdown = &genphy_shutdown,
 };
 
-static struct phy_driver dp83826nc_driver = {
+U_BOOT_PHY_DRIVER(dp83826nc) = {
 	.name = "TI DP83826NC",
 	.uid = 0x2000a110,
 	.mask = 0xfffffff0,
@@ -31,7 +30,7 @@
 	.shutdown = &genphy_shutdown,
 };
 
-static struct phy_driver dp83826c_driver = {
+U_BOOT_PHY_DRIVER(dp83826c) = {
 	.name = "TI DP83826C",
 	.uid = 0x2000a130,
 	.mask = 0xfffffff0,
@@ -41,7 +40,7 @@
 	.shutdown = &genphy_shutdown,
 };
 
-static struct phy_driver dp83825s_driver = {
+U_BOOT_PHY_DRIVER(dp83825s) = {
 	.name = "TI DP83825S",
 	.uid = 0x2000a140,
 	.mask = 0xfffffff0,
@@ -51,7 +50,7 @@
 	.shutdown = &genphy_shutdown,
 };
 
-static struct phy_driver dp83825i_driver = {
+U_BOOT_PHY_DRIVER(dp83825i) = {
 	.name = "TI DP83825I",
 	.uid = 0x2000a150,
 	.mask = 0xfffffff0,
@@ -61,7 +60,7 @@
 	.shutdown = &genphy_shutdown,
 };
 
-static struct phy_driver dp83825m_driver = {
+U_BOOT_PHY_DRIVER(dp83825m) = {
 	.name = "TI DP83825M",
 	.uid = 0x2000a160,
 	.mask = 0xfffffff0,
@@ -71,7 +70,7 @@
 	.shutdown = &genphy_shutdown,
 };
 
-static struct phy_driver dp83825cs_driver = {
+U_BOOT_PHY_DRIVER(dp83825cs) = {
 	.name = "TI DP83825CS",
 	.uid = 0x2000a170,
 	.mask = 0xfffffff0,
@@ -80,26 +79,3 @@
 	.startup = &genphy_startup,
 	.shutdown = &genphy_shutdown,
 };
-#endif /* CONFIG_PHY_TI_GENERIC */
-
-int phy_ti_init(void)
-{
-#ifdef CONFIG_PHY_TI_DP83867
-	phy_dp83867_init();
-#endif
-
-#ifdef CONFIG_PHY_TI_DP83869
-	phy_dp83869_init();
-#endif
-
-#ifdef CONFIG_PHY_TI_GENERIC
-	phy_register(&dp83822_driver);
-	phy_register(&dp83825s_driver);
-	phy_register(&dp83825i_driver);
-	phy_register(&dp83825m_driver);
-	phy_register(&dp83825cs_driver);
-	phy_register(&dp83826c_driver);
-	phy_register(&dp83826nc_driver);
-#endif
-	return 0;
-}
diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c
index eca26c9..c5cf0d7 100644
--- a/drivers/net/phy/vitesse.c
+++ b/drivers/net/phy/vitesse.c
@@ -293,7 +293,7 @@
 	return 0;
 }
 
-static struct phy_driver VSC8211_driver = {
+U_BOOT_PHY_DRIVER(vsc8211) = {
 	.name	= "Vitesse VSC8211",
 	.uid	= 0xfc4b0,
 	.mask	= 0xffff0,
@@ -303,7 +303,7 @@
 	.shutdown = &genphy_shutdown,
 };
 
-static struct phy_driver VSC8221_driver = {
+U_BOOT_PHY_DRIVER(vsc8221) = {
 	.name = "Vitesse VSC8221",
 	.uid = 0xfc550,
 	.mask = 0xffff0,
@@ -313,7 +313,7 @@
 	.shutdown = &genphy_shutdown,
 };
 
-static struct phy_driver VSC8244_driver = {
+U_BOOT_PHY_DRIVER(vsc8244) = {
 	.name = "Vitesse VSC8244",
 	.uid = 0xfc6c0,
 	.mask = 0xffff0,
@@ -323,7 +323,7 @@
 	.shutdown = &genphy_shutdown,
 };
 
-static struct phy_driver VSC8234_driver = {
+U_BOOT_PHY_DRIVER(vsc8234) = {
 	.name = "Vitesse VSC8234",
 	.uid = 0xfc620,
 	.mask = 0xffff0,
@@ -333,7 +333,7 @@
 	.shutdown = &genphy_shutdown,
 };
 
-static struct phy_driver VSC8574_driver = {
+U_BOOT_PHY_DRIVER(vsc8574) = {
 	.name = "Vitesse VSC8574",
 	.uid = 0x704a0,
 	.mask = 0xffff0,
@@ -343,7 +343,7 @@
 	.shutdown = &genphy_shutdown,
 };
 
-static struct phy_driver VSC8514_driver = {
+U_BOOT_PHY_DRIVER(vsc8514) = {
 	.name = "Vitesse VSC8514",
 	.uid = 0x70670,
 	.mask = 0xffff0,
@@ -353,7 +353,7 @@
 	.shutdown = &genphy_shutdown,
 };
 
-static struct phy_driver VSC8584_driver = {
+U_BOOT_PHY_DRIVER(vsc8584) = {
 	.name = "Vitesse VSC8584",
 	.uid = 0x707c0,
 	.mask = 0xffff0,
@@ -363,7 +363,7 @@
 	.shutdown = &genphy_shutdown,
 };
 
-static struct phy_driver VSC8601_driver = {
+U_BOOT_PHY_DRIVER(vsc8601) = {
 	.name = "Vitesse VSC8601",
 	.uid = 0x70420,
 	.mask = 0xffff0,
@@ -373,7 +373,7 @@
 	.shutdown = &genphy_shutdown,
 };
 
-static struct phy_driver VSC8641_driver = {
+U_BOOT_PHY_DRIVER(vsc8641) = {
 	.name = "Vitesse VSC8641",
 	.uid = 0x70430,
 	.mask = 0xffff0,
@@ -383,7 +383,7 @@
 	.shutdown = &genphy_shutdown,
 };
 
-static struct phy_driver VSC8662_driver = {
+U_BOOT_PHY_DRIVER(vsc8662) = {
 	.name = "Vitesse VSC8662",
 	.uid = 0x70660,
 	.mask = 0xffff0,
@@ -393,7 +393,7 @@
 	.shutdown = &genphy_shutdown,
 };
 
-static struct phy_driver VSC8664_driver = {
+U_BOOT_PHY_DRIVER(vsc8664) = {
 	.name = "Vitesse VSC8664",
 	.uid = 0x70660,
 	.mask = 0xffff0,
@@ -404,7 +404,7 @@
 };
 
 /* Vitesse bought Cicada, so we'll put these here */
-static struct phy_driver cis8201_driver = {
+U_BOOT_PHY_DRIVER(cis8201) = {
 	.name = "CIS8201",
 	.uid = 0xfc410,
 	.mask = 0xffff0,
@@ -414,7 +414,7 @@
 	.shutdown = &genphy_shutdown,
 };
 
-static struct phy_driver cis8204_driver = {
+U_BOOT_PHY_DRIVER(cis8204) = {
 	.name = "Cicada Cis8204",
 	.uid = 0xfc440,
 	.mask = 0xffff0,
@@ -423,22 +423,3 @@
 	.startup = &vitesse_startup,
 	.shutdown = &genphy_shutdown,
 };
-
-int phy_vitesse_init(void)
-{
-	phy_register(&VSC8641_driver);
-	phy_register(&VSC8601_driver);
-	phy_register(&VSC8234_driver);
-	phy_register(&VSC8244_driver);
-	phy_register(&VSC8211_driver);
-	phy_register(&VSC8221_driver);
-	phy_register(&VSC8574_driver);
-	phy_register(&VSC8584_driver);
-	phy_register(&VSC8514_driver);
-	phy_register(&VSC8662_driver);
-	phy_register(&VSC8664_driver);
-	phy_register(&cis8201_driver);
-	phy_register(&cis8204_driver);
-
-	return 0;
-}
diff --git a/drivers/net/phy/xilinx_gmii2rgmii.c b/drivers/net/phy/xilinx_gmii2rgmii.c
index 7376283..0b7436a 100644
--- a/drivers/net/phy/xilinx_gmii2rgmii.c
+++ b/drivers/net/phy/xilinx_gmii2rgmii.c
@@ -124,7 +124,7 @@
 	return 0;
 }
 
-static struct phy_driver gmii2rgmii_driver = {
+U_BOOT_PHY_DRIVER(gmii2rgmii) = {
 	.name = "XILINX GMII2RGMII",
 	.uid = PHY_GMII2RGMII_ID,
 	.mask = 0xffffffff,
@@ -135,10 +135,3 @@
 	.writeext = xilinxgmiitorgmii_extwrite,
 	.readext = xilinxgmiitorgmii_extread,
 };
-
-int phy_xilinx_gmii2rgmii_init(void)
-{
-	phy_register(&gmii2rgmii_driver);
-
-	return 0;
-}
diff --git a/drivers/net/phy/xilinx_phy.c b/drivers/net/phy/xilinx_phy.c
index 39dbfdb..1df639d 100644
--- a/drivers/net/phy/xilinx_phy.c
+++ b/drivers/net/phy/xilinx_phy.c
@@ -127,7 +127,7 @@
 	return 0;
 }
 
-static struct phy_driver xilinxphy_driver = {
+U_BOOT_PHY_DRIVER(xilinxphy) = {
 	.uid = XILINX_PHY_ID,
 	.mask = XILINX_PHY_ID_MASK,
 	.name = "Xilinx PCS/PMA PHY",
@@ -136,11 +136,3 @@
 	.startup = &xilinxphy_startup,
 	.shutdown = &genphy_shutdown,
 };
-
-int phy_xilinx_init(void)
-{
-	debug("%s\n", __func__);
-	phy_register(&xilinxphy_driver);
-
-	return 0;
-}
diff --git a/drivers/phy/phy-uclass.c b/drivers/phy/phy-uclass.c
index 3fef513..83e4b63 100644
--- a/drivers/phy/phy-uclass.c
+++ b/drivers/phy/phy-uclass.c
@@ -351,6 +351,28 @@
 	return ops->configure ? ops->configure(phy, params) : 0;
 }
 
+int generic_phy_set_mode(struct phy *phy, enum phy_mode mode, int submode)
+{
+	struct phy_ops const *ops;
+
+	if (!generic_phy_valid(phy))
+		return 0;
+	ops = phy_dev_ops(phy->dev);
+
+	return ops->set_mode ? ops->set_mode(phy, mode, submode) : 0;
+}
+
+int generic_phy_set_speed(struct phy *phy, int speed)
+{
+	struct phy_ops const *ops;
+
+	if (!generic_phy_valid(phy))
+		return 0;
+	ops = phy_dev_ops(phy->dev);
+
+	return ops->set_speed ? ops->set_speed(phy, speed) : 0;
+}
+
 int generic_phy_get_bulk(struct udevice *dev, struct phy_bulk *bulk)
 {
 	int i, ret, count;
diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c
index 77d3f37..067fae2 100644
--- a/drivers/serial/serial-uclass.c
+++ b/drivers/serial/serial-uclass.c
@@ -31,7 +31,7 @@
 static int serial_check_stdout(const void *blob, struct udevice **devp)
 {
 	int node = -1;
-	const char *str, *p, *name;
+	const char *str, *p;
 	int namelen;
 
 	/* Check for a chosen console */
@@ -39,20 +39,16 @@
 	if (str) {
 		p = strchr(str, ':');
 		namelen = p ? p - str : strlen(str);
+		/*
+		 * This also deals with things like
+		 *
+		 *	stdout-path = "serial0:115200n8";
+		 *
+		 * since fdt_path_offset_namelen() treats a str not
+		 * beginning with '/' as an alias and thus applies
+		 * fdt_get_alias_namelen() to it.
+		 */
 		node = fdt_path_offset_namelen(blob, str, namelen);
-
-		if (node < 0) {
-			/*
-			 * Deal with things like
-			 *	stdout-path = "serial0:115200n8";
-			 *
-			 * We need to look up the alias and then follow it to
-			 * the correct node.
-			 */
-			name = fdt_get_alias_namelen(blob, str, namelen);
-			if (name)
-				node = fdt_path_offset(blob, name);
-		}
 	}
 
 	if (node < 0)
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index b1d4b6c..4f435fd 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -573,6 +573,7 @@
 
 config FSL_ESPI
 	bool "Freescale eSPI driver"
+	depends on MPC85xx
 	imply SPI_FLASH_BAR
 	help
 	  Enable the Freescale eSPI driver. This driver can be used to
diff --git a/include/generic-phy.h b/include/generic-phy.h
index f8eddef..bee4de8 100644
--- a/include/generic-phy.h
+++ b/include/generic-phy.h
@@ -11,6 +11,29 @@
 
 struct ofnode_phandle_args;
 
+enum phy_mode {
+	PHY_MODE_INVALID,
+	PHY_MODE_USB_HOST,
+	PHY_MODE_USB_HOST_LS,
+	PHY_MODE_USB_HOST_FS,
+	PHY_MODE_USB_HOST_HS,
+	PHY_MODE_USB_HOST_SS,
+	PHY_MODE_USB_DEVICE,
+	PHY_MODE_USB_DEVICE_LS,
+	PHY_MODE_USB_DEVICE_FS,
+	PHY_MODE_USB_DEVICE_HS,
+	PHY_MODE_USB_DEVICE_SS,
+	PHY_MODE_USB_OTG,
+	PHY_MODE_UFS_HS_A,
+	PHY_MODE_UFS_HS_B,
+	PHY_MODE_PCIE,
+	PHY_MODE_ETHERNET,
+	PHY_MODE_MIPI_DPHY,
+	PHY_MODE_SATA,
+	PHY_MODE_LVDS,
+	PHY_MODE_DP
+};
+
 /**
  * struct phy - A handle to (allowing control of) a single phy port.
  *
@@ -69,73 +92,99 @@
 	int	(*init)(struct phy *phy);
 
 	/**
-	* exit - de-initialize the PHY device
-	*
-	* Hardware de-intialization should be done here. Every step done in
-	* init() should be undone here.
-	* This could be used to suspend the phy to reduce power consumption or
-	* to put the phy in a known condition before booting the OS (though it
-	* is NOT called automatically before booting the OS)
-	* If power_off() is not implemented, it must power down the phy.
-	*
-	* @phy:	PHY port to be de-initialized
-	* Return: 0 if OK, or a negative error code
-	*/
+	 * exit - de-initialize the PHY device
+	 *
+	 * Hardware de-intialization should be done here. Every step done in
+	 * init() should be undone here.
+	 * This could be used to suspend the phy to reduce power consumption or
+	 * to put the phy in a known condition before booting the OS (though it
+	 * is NOT called automatically before booting the OS)
+	 * If power_off() is not implemented, it must power down the phy.
+	 *
+	 * @phy:	PHY port to be de-initialized
+	 * Return: 0 if OK, or a negative error code
+	 */
 	int	(*exit)(struct phy *phy);
 
 	/**
-	* reset - resets a PHY device without shutting down
-	*
-	* @phy:	PHY port to be reset
-	*
-	* During runtime, the PHY may need to be reset in order to
-	* re-establish connection etc without being shut down or exit.
-	*
-	* Return: 0 if OK, or a negative error code
-	*/
+	 * reset - resets a PHY device without shutting down
+	 *
+	 * @phy:	PHY port to be reset
+	 *
+	 * During runtime, the PHY may need to be reset in order to
+	 * re-establish connection etc without being shut down or exit.
+	 *
+	 * Return: 0 if OK, or a negative error code
+	 */
 	int	(*reset)(struct phy *phy);
 
 	/**
-	* power_on - power on a PHY device
-	*
-	* @phy:	PHY port to be powered on
-	*
-	* During runtime, the PHY may need to be powered on or off several
-	* times. This function is used to power on the PHY. It relies on the
-	* setup done in init(). If init() is not implemented, it must take care
-	* of setting up the context (PLLs, ...)
-	*
-	* Return: 0 if OK, or a negative error code
-	*/
+	 * power_on - power on a PHY device
+	 *
+	 * @phy:	PHY port to be powered on
+	 *
+	 * During runtime, the PHY may need to be powered on or off several
+	 * times. This function is used to power on the PHY. It relies on the
+	 * setup done in init(). If init() is not implemented, it must take care
+	 * of setting up the context (PLLs, ...)
+	 *
+	 * Return: 0 if OK, or a negative error code
+	 */
 	int	(*power_on)(struct phy *phy);
 
 	/**
-	* power_off - power off a PHY device
-	*
-	* @phy:	PHY port to be powered off
-	*
-	* During runtime, the PHY may need to be powered on or off several
-	* times. This function is used to power off the PHY. Except if
-	* init()/deinit() are not implemented, it must not de-initialize
-	* everything.
-	*
-	* Return: 0 if OK, or a negative error code
-	*/
+	 * power_off - power off a PHY device
+	 *
+	 * @phy:	PHY port to be powered off
+	 *
+	 * During runtime, the PHY may need to be powered on or off several
+	 * times. This function is used to power off the PHY. Except if
+	 * init()/deinit() are not implemented, it must not de-initialize
+	 * everything.
+	 *
+	 * Return: 0 if OK, or a negative error code
+	 */
 	int	(*power_off)(struct phy *phy);
 
 	/**
-	* configure - configure a PHY device
-	*
-	* @phy:	PHY port to be configured
-	* @params: PHY Parameters, underlying data is specific to the PHY function
-	*
-	* During runtime, the PHY may need to be configured for it's main function.
-	* This function configures the PHY for it's main function following
-	* power_on/off() after beeing initialized.
-	*
-	* Return: 0 if OK, or a negative error code
-	*/
+	 * configure - configure a PHY device
+	 *
+	 * @phy:	PHY port to be configured
+	 * @params: PHY Parameters, underlying data is specific to the PHY function
+	 *
+	 * During runtime, the PHY may need to be configured for it's main function.
+	 * This function configures the PHY for it's main function following
+	 * power_on/off() after being initialized.
+	 *
+	 * Return: 0 if OK, or a negative error code
+	 */
 	int	(*configure)(struct phy *phy, void *params);
+
+	/**
+	 * set_mode - set PHY device mode
+	 *
+	 * @phy:	PHY port to be configured
+	 * @mode: PHY mode
+	 * @submode: PHY submode
+	 *
+	 * Configure PHY mode (e.g. USB, Ethernet, ...) and submode
+	 * (e.g. for Ethernet this can be RGMII).
+	 *
+	 * Return: 0 if OK, or a negative error code
+	 */
+	int	(*set_mode)(struct phy *phy, enum phy_mode mode, int submode);
+
+	/**
+	 * set_speed - set PHY device speed
+	 *
+	 * @phy:	PHY port to be configured
+	 * @speed: PHY speed
+	 *
+	 * Configure PHY speed (e.g. for Ethernet, this could be 10 or 100 ...).
+	 *
+	 * Return: 0 if OK, or a negative error code
+	 */
+	int	(*set_speed)(struct phy *phy, int speed);
 };
 
 /**
@@ -206,6 +255,24 @@
  */
 int generic_phy_configure(struct phy *phy, void *params);
 
+/**
+ * generic_phy_set_mode() - set PHY device mode
+ *
+ * @phy:	PHY port to be configured
+ * @mode: PHY mode
+ * @submode: PHY submode
+ * Return: 0 if OK, or a negative error code
+ */
+int generic_phy_set_mode(struct phy *phy, enum phy_mode mode, int submode);
+
+/**
+ * generic_phy_set_speed() - set PHY device speed
+ *
+ * @phy:	PHY port to be configured
+ * @speed: PHY speed
+ * Return: 0 if OK, or a negative error code
+ */
+int generic_phy_set_speed(struct phy *phy, int speed);
 
 /**
  * generic_phy_get_by_index() - Get a PHY device by integer index.
@@ -389,6 +456,21 @@
 	return 0;
 }
 
+static inline int generic_phy_configure(struct phy *phy, void *params)
+{
+	return 0;
+}
+
+static inline int generic_phy_set_mode(struct phy *phy, enum phy_mode mode, int submode)
+{
+	return 0;
+}
+
+static inline int generic_phy_set_speed(struct phy *phy, int speed)
+{
+	return 0;
+}
+
 static inline int generic_phy_get_by_index(struct udevice *user, int index,
 			     struct phy *phy)
 {
diff --git a/include/linux/mdio.h b/include/linux/mdio.h
index 6e821d9..b7c8451 100644
--- a/include/linux/mdio.h
+++ b/include/linux/mdio.h
@@ -44,6 +44,7 @@
 #define MDIO_AN_ADVERTISE	16	/* AN advertising (base page) */
 #define MDIO_AN_LPA		19	/* AN LP abilities (base page) */
 #define MDIO_PCS_EEE_ABLE	20	/* EEE Capability register */
+#define MDIO_PMA_NG_EXTABLE	21	/* 2.5G/5G PMA/PMD extended ability */
 #define MDIO_PCS_EEE_WK_ERR	22	/* EEE wake error counter */
 #define MDIO_PHYXS_LNSTAT	24	/* PHY XGXS lane state */
 #define MDIO_AN_EEE_ADV		60	/* EEE advertisement */
@@ -91,6 +92,10 @@
 #define MDIO_CTRL1_SPEED10G		(MDIO_CTRL1_SPEEDSELEXT | 0x00)
 /* 10PASS-TS/2BASE-TL */
 #define MDIO_CTRL1_SPEED10P2B		(MDIO_CTRL1_SPEEDSELEXT | 0x04)
+/* 2.5 Gb/s */
+#define MDIO_CTRL1_SPEED2_5G		(MDIO_CTRL1_SPEEDSELEXT | 0x18)
+/* 5 Gb/s */
+#define MDIO_CTRL1_SPEED5G		(MDIO_CTRL1_SPEEDSELEXT | 0x1c)
 
 /* Status register 1. */
 #define MDIO_STAT1_LPOWERABLE		0x0002	/* Low-power ability */
@@ -111,6 +116,8 @@
 #define MDIO_PMA_SPEED_100		0x0020	/* 100M capable */
 #define MDIO_PMA_SPEED_10		0x0040	/* 10M capable */
 #define MDIO_PCS_SPEED_10P2B		0x0002	/* 10PASS-TS/2BASE-TL capable */
+#define MDIO_PCS_SPEED_2_5G		0x0040	/* 2.5G capable */
+#define MDIO_PCS_SPEED_5G		0x0080	/* 5G capable */
 
 /* Device present registers. */
 #define MDIO_DEVS_PRESENT(devad)	(1 << (devad))
@@ -150,6 +157,8 @@
 #define MDIO_PMA_CTRL2_1000BKX		0x000d	/* 1000BASE-KX type */
 #define MDIO_PMA_CTRL2_100BTX		0x000e	/* 100BASE-TX type */
 #define MDIO_PMA_CTRL2_10BT		0x000f	/* 10BASE-T type */
+#define MDIO_PMA_CTRL2_2_5GBT		0x0030  /* 2.5GBaseT type */
+#define MDIO_PMA_CTRL2_5GBT		0x0031  /* 5GBaseT type */
 #define MDIO_PCS_CTRL2_TYPE		0x0003	/* PCS type selection */
 #define MDIO_PCS_CTRL2_10GBR		0x0000	/* 10GBASE-R type */
 #define MDIO_PCS_CTRL2_10GBX		0x0001	/* 10GBASE-X type */
@@ -203,6 +212,7 @@
 #define MDIO_PMA_EXTABLE_1000BKX	0x0040	/* 1000BASE-KX ability */
 #define MDIO_PMA_EXTABLE_100BTX		0x0080	/* 100BASE-TX ability */
 #define MDIO_PMA_EXTABLE_10BT		0x0100	/* 10BASE-T ability */
+#define MDIO_PMA_EXTABLE_NBT		0x4000  /* 2.5/5GBASE-T ability */
 
 /* PHY XGXS lane state register. */
 #define MDIO_PHYXS_LNSTAT_SYNC0		0x0001
@@ -239,9 +249,13 @@
 #define MDIO_PCS_10GBRT_STAT2_BER	0x3f00
 
 /* AN 10GBASE-T control register. */
+#define MDIO_AN_10GBT_CTRL_ADV2_5G	0x0080	/* Advertise 2.5GBASE-T */
+#define MDIO_AN_10GBT_CTRL_ADV5G	0x0100	/* Advertise 5GBASE-T */
 #define MDIO_AN_10GBT_CTRL_ADV10G	0x1000	/* Advertise 10GBASE-T */
 
 /* AN 10GBASE-T status register. */
+#define MDIO_AN_10GBT_STAT_LP2_5G	0x0020  /* LP is 2.5GBT capable */
+#define MDIO_AN_10GBT_STAT_LP5G		0x0040  /* LP is 5GBT capable */
 #define MDIO_AN_10GBT_STAT_LPTRR	0x0200	/* LP training reset req. */
 #define MDIO_AN_10GBT_STAT_LPLTABLE	0x0400	/* LP loop timing ability */
 #define MDIO_AN_10GBT_STAT_LP10G	0x0800	/* LP is 10GBT capable */
@@ -270,6 +284,10 @@
 #define MDIO_EEE_10GKX4		0x0020	/* 10G KX4 EEE cap */
 #define MDIO_EEE_10GKR		0x0040	/* 10G KR EEE cap */
 
+/* 2.5G/5G Extended abilities register. */
+#define MDIO_PMA_NG_EXTABLE_2_5GBT	0x0001	/* 2.5GBASET ability */
+#define MDIO_PMA_NG_EXTABLE_5GBT	0x0002	/* 5GBASET ability */
+
 /* LASI RX_ALARM control/status registers. */
 #define MDIO_PMA_LASI_RX_PHYXSLFLT	0x0001	/* PHY XS RX local fault */
 #define MDIO_PMA_LASI_RX_PCSLFLT	0x0008	/* PCS RX local fault */
diff --git a/include/lmb.h b/include/lmb.h
index 7298c2c..07bf221 100644
--- a/include/lmb.h
+++ b/include/lmb.h
@@ -35,6 +35,24 @@
 	enum lmb_flags flags;
 };
 
+/*
+ * For regions size management, see LMB configuration in KConfig
+ * all the #if test are done with CONFIG_LMB_USE_MAX_REGIONS (boolean)
+ *
+ * case 1. CONFIG_LMB_USE_MAX_REGIONS is defined (legacy mode)
+ *         => CONFIG_LMB_MAX_REGIONS is used to configure the region size,
+ *         directly in the array lmb_region.region[], with the same
+ *         configuration for memory and reserved regions.
+ *
+ * case 2. CONFIG_LMB_USE_MAX_REGIONS is not defined, the size of each
+ *         region is configurated *independently* with
+ *         => CONFIG_LMB_MEMORY_REGIONS: struct lmb.memory_regions
+ *         => CONFIG_LMB_RESERVED_REGIONS: struct lmb.reserved_regions
+ *         lmb_region.region is only a pointer to the correct buffer,
+ *         initialized in lmb_init(). This configuration is useful to manage
+ *         more reserved memory regions with CONFIG_LMB_RESERVED_REGIONS.
+ */
+
 /**
  * struct lmb_region - Description of a set of region.
  *
@@ -68,7 +86,7 @@
 struct lmb {
 	struct lmb_region memory;
 	struct lmb_region reserved;
-#ifdef CONFIG_LMB_MEMORY_REGIONS
+#if !IS_ENABLED(CONFIG_LMB_USE_MAX_REGIONS)
 	struct lmb_property memory_regions[CONFIG_LMB_MEMORY_REGIONS];
 	struct lmb_property reserved_regions[CONFIG_LMB_RESERVED_REGIONS];
 #endif
diff --git a/include/marvell_phy.h b/include/marvell_phy.h
new file mode 100644
index 0000000..0f06c22
--- /dev/null
+++ b/include/marvell_phy.h
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _MARVELL_PHY_H
+#define _MARVELL_PHY_H
+
+/* Mask used for ID comparisons */
+#define MARVELL_PHY_ID_MASK		0xfffffff0
+
+/* Known PHY IDs */
+#define MARVELL_PHY_ID_88E1101		0x01410c60
+#define MARVELL_PHY_ID_88E1112		0x01410c90
+#define MARVELL_PHY_ID_88E1111		0x01410cc0
+#define MARVELL_PHY_ID_88E1118		0x01410e10
+#define MARVELL_PHY_ID_88E1121R		0x01410cb0
+#define MARVELL_PHY_ID_88E1145		0x01410cd0
+#define MARVELL_PHY_ID_88E1149R		0x01410e50
+#define MARVELL_PHY_ID_88E1240		0x01410e30
+#define MARVELL_PHY_ID_88E1318S		0x01410e90
+#define MARVELL_PHY_ID_88E1340S		0x01410dc0
+#define MARVELL_PHY_ID_88E1116R		0x01410e40
+#define MARVELL_PHY_ID_88E1510		0x01410dd0
+#define MARVELL_PHY_ID_88E1540		0x01410eb0
+#define MARVELL_PHY_ID_88E1545		0x01410ea0
+#define MARVELL_PHY_ID_88E1548P		0x01410ec0
+#define MARVELL_PHY_ID_88E3016		0x01410e60
+#define MARVELL_PHY_ID_88X3310		0x002b09a0
+#define MARVELL_PHY_ID_88E2110		0x002b09b0
+#define MARVELL_PHY_ID_88X2222		0x01410f10
+
+/* Marvel 88E1111 in Finisar SFP module with modified PHY ID */
+#define MARVELL_PHY_ID_88E1111_FINISAR	0x01ff0cc0
+
+/* These Ethernet switch families contain embedded PHYs, but they do
+ * not have a model ID. So the switch driver traps reads to the ID2
+ * register and returns the switch family ID
+ */
+#define MARVELL_PHY_ID_88E6341_FAMILY	0x01410f41
+#define MARVELL_PHY_ID_88E6390_FAMILY	0x01410f90
+#define MARVELL_PHY_ID_88E6393_FAMILY	0x002b0b9b
+
+#define MARVELL_PHY_FAMILY_ID(id)	((id) >> 4)
+
+/* struct phy_device dev_flags definitions */
+#define MARVELL_PHY_M1145_FLAGS_RESISTANCE	0x00000001
+#define MARVELL_PHY_M1118_DNS323_LEDS		0x00000002
+#define MARVELL_PHY_LED0_LINK_LED1_ACTIVE	0x00000004
+
+#endif /* _MARVELL_PHY_H */
diff --git a/include/phy.h b/include/phy.h
index 87aa86c..a837fed 100644
--- a/include/phy.h
+++ b/include/phy.h
@@ -125,8 +125,6 @@
 	int (*write_mmd)(struct phy_device *phydev, int devad, int reg,
 			 u16 val);
 
-	struct list_head list;
-
 	/* driver private data */
 	ulong data;
 };
@@ -173,10 +171,6 @@
 	int asym_pause;
 };
 
-#ifdef CONFIG_PHYLIB_10G
-extern struct phy_driver gen10g_driver;
-#endif
-
 /**
  * phy_init() - Initializes the PHY drivers
  * This function registers all available PHY drivers
@@ -288,6 +282,37 @@
 		return dev_ofnode(phydev->dev);
 }
 
+/**
+ * phy_read_mmd_poll_timeout - Periodically poll a PHY register until a
+ *                             condition is met or a timeout occurs
+ *
+ * @phydev: The phy_device struct
+ * @devaddr: The MMD to read from
+ * @regnum: The register on the MMD to read
+ * @val: Variable to read the register into
+ * @cond: Break condition (usually involving @val)
+ * @sleep_us: Maximum time to sleep between reads in us (0
+ *            tight-loops).  Should be less than ~20ms since usleep_range
+ *            is used (see Documentation/timers/timers-howto.rst).
+ * @timeout_us: Timeout in us, 0 means never timeout
+ * @sleep_before_read: if it is true, sleep @sleep_us before read.
+ * Returns 0 on success and -ETIMEDOUT upon a timeout. In either
+ * case, the last read value at @args is stored in @val. Must not
+ * be called from atomic context if sleep_us or timeout_us are used.
+ */
+#define phy_read_mmd_poll_timeout(phydev, devaddr, regnum, val, cond, \
+				  sleep_us, timeout_us, sleep_before_read) \
+({ \
+	int __ret = read_poll_timeout(phy_read_mmd, val, (cond) || val < 0, \
+				  sleep_us, timeout_us, \
+				  phydev, devaddr, regnum); \
+	if (val <  0) \
+		__ret = val; \
+	if (__ret) \
+		dev_err(phydev->dev, "%s failed: %d\n", __func__, __ret); \
+	__ret; \
+})
+
 int phy_read(struct phy_device *phydev, int devad, int regnum);
 int phy_write(struct phy_device *phydev, int devad, int regnum, u16 val);
 void phy_mmd_start_indirect(struct phy_device *phydev, int devad, int regnum);
@@ -295,11 +320,14 @@
 int phy_write_mmd(struct phy_device *phydev, int devad, int regnum, u16 val);
 int phy_set_bits_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val);
 int phy_clear_bits_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val);
+int phy_modify_mmd_changed(struct phy_device *phydev, int devad, u32 regnum,
+			   u16 mask, u16 set);
+int phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum,
+		   u16 mask, u16 set);
 
 int phy_startup(struct phy_device *phydev);
 int phy_config(struct phy_device *phydev);
 int phy_shutdown(struct phy_device *phydev);
-int phy_register(struct phy_driver *drv);
 int phy_set_supported(struct phy_device *phydev, u32 max_speed);
 int phy_modify(struct phy_device *phydev, int devad, int regnum, u16 mask,
 	       u16 set);
@@ -315,35 +343,12 @@
 int gen10g_shutdown(struct phy_device *phydev);
 int gen10g_discover_mmds(struct phy_device *phydev);
 
-int phy_b53_init(void);
-int phy_mv88e61xx_init(void);
-int phy_adin_init(void);
-int phy_aquantia_init(void);
-int phy_atheros_init(void);
-int phy_broadcom_init(void);
-int phy_cortina_init(void);
-int phy_cortina_access_init(void);
-int phy_davicom_init(void);
-int phy_et1011c_init(void);
-int phy_lxt_init(void);
-int phy_marvell_init(void);
-int phy_micrel_ksz8xxx_init(void);
-int phy_micrel_ksz90x1_init(void);
-int phy_meson_gxl_init(void);
-int phy_natsemi_init(void);
-int phy_nxp_c45_tja11xx_init(void);
-int phy_nxp_tja11xx_init(void);
-int phy_realtek_init(void);
-int phy_smsc_init(void);
-int phy_teranetics_init(void);
-int phy_ti_init(void);
-int phy_vitesse_init(void);
-int phy_xilinx_init(void);
-int phy_xway_init(void);
-int phy_mscc_init(void);
-int phy_fixed_init(void);
-int phy_ncsi_init(void);
-int phy_xilinx_gmii2rgmii_init(void);
+/**
+ * U_BOOT_PHY_DRIVER() - Declare a new U-Boot driver
+ * @__name: name of the driver
+ */
+#define U_BOOT_PHY_DRIVER(__name)					\
+	ll_entry_declare(struct phy_driver, __name, phy_driver)
 
 int board_phy_config(struct phy_device *phydev);
 int get_phy_id(struct mii_dev *bus, int addr, int devad, u32 *phy_id);
diff --git a/include/phy_interface.h b/include/phy_interface.h
index fed3357..31be322 100644
--- a/include/phy_interface.h
+++ b/include/phy_interface.h
@@ -14,63 +14,95 @@
 
 typedef enum {
 	PHY_INTERFACE_MODE_NA, /* don't touch */
+	PHY_INTERFACE_MODE_INTERNAL,
 	PHY_INTERFACE_MODE_MII,
 	PHY_INTERFACE_MODE_GMII,
 	PHY_INTERFACE_MODE_SGMII,
-	PHY_INTERFACE_MODE_SGMII_2500,
-	PHY_INTERFACE_MODE_QSGMII,
 	PHY_INTERFACE_MODE_TBI,
+	PHY_INTERFACE_MODE_REVMII,
 	PHY_INTERFACE_MODE_RMII,
+	PHY_INTERFACE_MODE_REVRMII,
 	PHY_INTERFACE_MODE_RGMII,
 	PHY_INTERFACE_MODE_RGMII_ID,
 	PHY_INTERFACE_MODE_RGMII_RXID,
 	PHY_INTERFACE_MODE_RGMII_TXID,
 	PHY_INTERFACE_MODE_RTBI,
+	PHY_INTERFACE_MODE_SMII,
+	PHY_INTERFACE_MODE_XGMII,
+	PHY_INTERFACE_MODE_XLGMII,
+	PHY_INTERFACE_MODE_MOCA,
+	PHY_INTERFACE_MODE_QSGMII,
+	PHY_INTERFACE_MODE_TRGMII,
+	PHY_INTERFACE_MODE_100BASEX,
 	PHY_INTERFACE_MODE_1000BASEX,
 	PHY_INTERFACE_MODE_2500BASEX,
-	PHY_INTERFACE_MODE_XGMII,
-	PHY_INTERFACE_MODE_XAUI,
+	PHY_INTERFACE_MODE_5GBASER,
 	PHY_INTERFACE_MODE_RXAUI,
-	PHY_INTERFACE_MODE_SFI,
-	PHY_INTERFACE_MODE_INTERNAL,
+	PHY_INTERFACE_MODE_XAUI,
+	/* 10GBASE-R, XFI, SFI - single lane 10G Serdes */
+	PHY_INTERFACE_MODE_10GBASER,
+	PHY_INTERFACE_MODE_25GBASER,
+	PHY_INTERFACE_MODE_USXGMII,
+	/* 10GBASE-KR - with Clause 73 AN */
+	PHY_INTERFACE_MODE_10GKR,
+	PHY_INTERFACE_MODE_QUSGMII,
+	PHY_INTERFACE_MODE_1000BASEKX,
+#if defined(CONFIG_ARCH_LX2160A) || defined(CONFIG_ARCH_LX2162A)
+	/* LX2160A SERDES modes */
 	PHY_INTERFACE_MODE_25G_AUI,
 	PHY_INTERFACE_MODE_XLAUI,
 	PHY_INTERFACE_MODE_CAUI2,
 	PHY_INTERFACE_MODE_CAUI4,
+#endif
+#if defined(CONFIG_PHY_NCSI)
 	PHY_INTERFACE_MODE_NCSI,
-	PHY_INTERFACE_MODE_10GBASER,
-	PHY_INTERFACE_MODE_USXGMII,
+#endif
 	PHY_INTERFACE_MODE_MAX,
 } phy_interface_t;
 
 static const char * const phy_interface_strings[] = {
-	[PHY_INTERFACE_MODE_NA]		= "",
+	[PHY_INTERFACE_MODE_NA]			= "",
+	[PHY_INTERFACE_MODE_INTERNAL]		= "internal",
 	[PHY_INTERFACE_MODE_MII]		= "mii",
 	[PHY_INTERFACE_MODE_GMII]		= "gmii",
 	[PHY_INTERFACE_MODE_SGMII]		= "sgmii",
-	[PHY_INTERFACE_MODE_SGMII_2500]		= "sgmii-2500",
-	[PHY_INTERFACE_MODE_QSGMII]		= "qsgmii",
 	[PHY_INTERFACE_MODE_TBI]		= "tbi",
+	[PHY_INTERFACE_MODE_REVMII]		= "rev-mii",
 	[PHY_INTERFACE_MODE_RMII]		= "rmii",
+	[PHY_INTERFACE_MODE_REVRMII]		= "rev-rmii",
 	[PHY_INTERFACE_MODE_RGMII]		= "rgmii",
 	[PHY_INTERFACE_MODE_RGMII_ID]		= "rgmii-id",
 	[PHY_INTERFACE_MODE_RGMII_RXID]		= "rgmii-rxid",
 	[PHY_INTERFACE_MODE_RGMII_TXID]		= "rgmii-txid",
 	[PHY_INTERFACE_MODE_RTBI]		= "rtbi",
+	[PHY_INTERFACE_MODE_SMII]		= "smii",
+	[PHY_INTERFACE_MODE_XGMII]		= "xgmii",
+	[PHY_INTERFACE_MODE_XLGMII]		= "xlgmii",
+	[PHY_INTERFACE_MODE_MOCA]		= "moca",
+	[PHY_INTERFACE_MODE_QSGMII]		= "qsgmii",
+	[PHY_INTERFACE_MODE_TRGMII]		= "trgmii",
 	[PHY_INTERFACE_MODE_1000BASEX]		= "1000base-x",
+	[PHY_INTERFACE_MODE_1000BASEKX]		= "1000base-kx",
 	[PHY_INTERFACE_MODE_2500BASEX]		= "2500base-x",
-	[PHY_INTERFACE_MODE_XGMII]		= "xgmii",
-	[PHY_INTERFACE_MODE_XAUI]		= "xaui",
+	[PHY_INTERFACE_MODE_5GBASER]		= "5gbase-r",
 	[PHY_INTERFACE_MODE_RXAUI]		= "rxaui",
-	[PHY_INTERFACE_MODE_SFI]		= "sfi",
-	[PHY_INTERFACE_MODE_INTERNAL]		= "internal",
+	[PHY_INTERFACE_MODE_XAUI]		= "xaui",
+	[PHY_INTERFACE_MODE_10GBASER]		= "10gbase-r",
+	[PHY_INTERFACE_MODE_25GBASER]		= "25gbase-r",
+	[PHY_INTERFACE_MODE_USXGMII]		= "usxgmii",
+	[PHY_INTERFACE_MODE_10GKR]		= "10gbase-kr",
+	[PHY_INTERFACE_MODE_100BASEX]		= "100base-x",
+	[PHY_INTERFACE_MODE_QUSGMII]		= "qusgmii",
+#if defined(CONFIG_ARCH_LX2160A) || defined(CONFIG_ARCH_LX2162A)
+	/* LX2160A SERDES modes */
 	[PHY_INTERFACE_MODE_25G_AUI]		= "25g-aui",
 	[PHY_INTERFACE_MODE_XLAUI]		= "xlaui4",
 	[PHY_INTERFACE_MODE_CAUI2]		= "caui2",
 	[PHY_INTERFACE_MODE_CAUI4]		= "caui4",
+#endif
+#if defined(CONFIG_PHY_NCSI)
 	[PHY_INTERFACE_MODE_NCSI]		= "NC-SI",
-	[PHY_INTERFACE_MODE_10GBASER]		= "10gbase-r",
-	[PHY_INTERFACE_MODE_USXGMII]		= "usxgmii",
+#endif
 };
 
 /* Backplane modes:
diff --git a/lib/Kconfig b/lib/Kconfig
index 202a34a..d8dac09 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -1057,7 +1057,6 @@
 
 config LMB_USE_MAX_REGIONS
 	bool "Use a common number of memory and reserved regions in lmb lib"
-	depends on LMB
 	default y
 	help
 	  Define the number of supported memory regions in the library logical
@@ -1067,7 +1066,7 @@
 
 config LMB_MAX_REGIONS
 	int "Number of memory and reserved regions in lmb lib"
-	depends on LMB && LMB_USE_MAX_REGIONS
+	depends on LMB_USE_MAX_REGIONS
 	default 16
 	help
 	  Define the number of supported regions, memory and reserved, in the
@@ -1075,7 +1074,7 @@
 
 config LMB_MEMORY_REGIONS
 	int "Number of memory regions in lmb lib"
-	depends on LMB && !LMB_USE_MAX_REGIONS
+	depends on !LMB_USE_MAX_REGIONS
 	default 8
 	help
 	  Define the number of supported memory regions in the library logical
@@ -1084,7 +1083,7 @@
 
 config LMB_RESERVED_REGIONS
 	int "Number of reserved regions in lmb lib"
-	depends on LMB && !LMB_USE_MAX_REGIONS
+	depends on !LMB_USE_MAX_REGIONS
 	default 8
 	help
 	  Define the number of supported reserved regions in the library logical
diff --git a/lib/lmb.c b/lib/lmb.c
index 2444b2a..b2c233e 100644
--- a/lib/lmb.c
+++ b/lib/lmb.c
@@ -27,7 +27,7 @@
 	enum lmb_flags flags;
 	int i;
 
-	printf(" %s.cnt  = 0x%lx\n", name, rgn->cnt);
+	printf(" %s.cnt = 0x%lx / max = 0x%lx\n", name, rgn->cnt, rgn->max);
 
 	for (i = 0; i < rgn->cnt; i++) {
 		base = rgn->region[i].base;
@@ -110,7 +110,7 @@
 #if IS_ENABLED(CONFIG_LMB_USE_MAX_REGIONS)
 	lmb->memory.max = CONFIG_LMB_MAX_REGIONS;
 	lmb->reserved.max = CONFIG_LMB_MAX_REGIONS;
-#elif defined(CONFIG_LMB_MEMORY_REGIONS)
+#else
 	lmb->memory.max = CONFIG_LMB_MEMORY_REGIONS;
 	lmb->reserved.max = CONFIG_LMB_RESERVED_REGIONS;
 	lmb->memory.region = lmb->memory_regions;
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 2d13e68..e87503e 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -674,6 +674,7 @@
 
 		case 'x':
 			flags |= SMALL;
+		/* fallthrough */
 		case 'X':
 			base = 16;
 			break;
@@ -681,8 +682,10 @@
 		case 'd':
 			if (fmt[1] == 'E')
 				flags |= ERRSTR;
+		/* fallthrough */
 		case 'i':
 			flags |= SIGN;
+		/* fallthrough */
 		case 'u':
 			break;
 
diff --git a/net/eth_common.c b/net/eth_common.c
index 82d527a..c94a7ba 100644
--- a/net/eth_common.c
+++ b/net/eth_common.c
@@ -37,7 +37,7 @@
 	miiphy_init();
 #endif
 
-#ifdef CONFIG_PHYLIB
+#if defined(CONFIG_NEEDS_MANUAL_RELOC) && defined(CONFIG_PHYLIB)
 	phy_init();
 #endif
 #endif
diff --git a/tools/env/fw_env_main.c b/tools/env/fw_env_main.c
index 1d193bd..0b201b9 100644
--- a/tools/env/fw_env_main.c
+++ b/tools/env/fw_env_main.c
@@ -73,7 +73,7 @@
 		" -c, --config         configuration file, default:" CONFIG_FILE "\n"
 #endif
 		" -n, --noheader       do not repeat variable name in output\n"
-		" -l, --lock           lock node, default:/var/lock\n"
+		" -l, --lock           lock node, default:/run\n"
 		"\n");
 }
 
@@ -88,7 +88,7 @@
 #ifdef CONFIG_FILE
 		" -c, --config         configuration file, default:" CONFIG_FILE "\n"
 #endif
-		" -l, --lock           lock node, default:/var/lock\n"
+		" -l, --lock           lock node, default:/run\n"
 		" -s, --script         batch mode to minimize writes\n"
 		"\n"
 		"Examples:\n"
@@ -206,7 +206,7 @@
 
 int main(int argc, char *argv[])
 {
-	char *lockname = "/var/lock/" CMD_PRINTENV ".lock";
+	char *lockname = "/run/" CMD_PRINTENV ".lock";
 	int lockfd = -1;
 	int retval = EXIT_SUCCESS;
 	char *_cmdname;
diff --git a/tools/fdt_add_pubkey.c b/tools/fdt_add_pubkey.c
index 999f5a7..5582d7a 100644
--- a/tools/fdt_add_pubkey.c
+++ b/tools/fdt_add_pubkey.c
@@ -10,7 +10,7 @@
 static const char *require_keys; /* -r <conf|image> */
 static const char *keydest; /* argv[n] */
 
-static void print_usage(const char *msg)
+static void __attribute__((__noreturn__)) print_usage(const char *msg)
 {
 	fprintf(stderr, "Error: %s\n", msg);
 	fprintf(stderr, "Usage: %s [-a <algo>] [-k <keydir>] [-n <keyname>] [-r <conf|image>]"
@@ -19,7 +19,7 @@
 	exit(EXIT_FAILURE);
 }
 
-static void print_help(void)
+static void __attribute__((__noreturn__)) print_help(void)
 {
 	fprintf(stderr, "Options:\n"
 		"\t-a <algo>       Cryptographic algorithm. Optional parameter, default value: sha1,rsa2048\n"