diff mbox series

[net-next,v2,3/4] mlxbf_gige: add BlueField-3 Serdes configuration

Message ID 20221109224752.17664-4-davthompson@nvidia.com (mailing list archive)
State Changes Requested
Delegated to: Netdev Maintainers
Headers show
Series mlxbf_gige: add BlueField-3 support | expand

Checks

Context Check Description
netdev/tree_selection success Clearly marked for net-next, async
netdev/fixes_present success Fixes tag not required for -next series
netdev/subject_prefix success Link
netdev/cover_letter success Series has a cover letter
netdev/patch_count success Link
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 0 this patch: 0
netdev/cc_maintainers success CCed 7 of 7 maintainers
netdev/build_clang success Errors and warnings before: 0 this patch: 0
netdev/module_param success Was 0 now: 0
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 0 this patch: 0
netdev/checkpatch warning WARNING: added, moved or deleted file(s), does MAINTAINERS need updating? WARNING: line length of 81 exceeds 80 columns WARNING: line length of 82 exceeds 80 columns WARNING: line length of 83 exceeds 80 columns WARNING: line length of 84 exceeds 80 columns WARNING: line length of 85 exceeds 80 columns WARNING: line length of 86 exceeds 80 columns WARNING: line length of 87 exceeds 80 columns WARNING: line length of 88 exceeds 80 columns WARNING: line length of 90 exceeds 80 columns WARNING: line length of 91 exceeds 80 columns WARNING: line length of 93 exceeds 80 columns
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

David Thompson Nov. 9, 2022, 10:47 p.m. UTC
The BlueField-3 out-of-band Ethernet interface requires
SerDes configuration. There are two aspects to this:

Configuration of PLL:
    1) Initialize UPHY registers to values dependent on p1clk clock
    2) Load PLL best known values via the gateway register
    3) Set the fuses to tune up the SerDes voltage
    4) Lock the PLL
    5) Get the lanes out of functional reset.
    6) Configure the UPHY microcontroller via gateway reads/writes

Configuration of lanes:
    1) Configure and open TX lanes
    2) Configure and open RX lanes

Signed-off-by: David Thompson <davthompson@nvidia.com>
Signed-off-by: Asmaa Mnebhi <asmaa@nvidia.com>
---
 .../net/ethernet/mellanox/mlxbf_gige/Makefile |    3 +-
 .../ethernet/mellanox/mlxbf_gige/mlxbf_gige.h |    4 +-
 .../mellanox/mlxbf_gige/mlxbf_gige_main.c     |   57 +-
 .../mellanox/mlxbf_gige/mlxbf_gige_mdio.c     |   37 -
 .../mellanox/mlxbf_gige/mlxbf_gige_uphy.c     | 1173 +++++++++++++++++
 .../mellanox/mlxbf_gige/mlxbf_gige_uphy.h     |  398 ++++++
 6 files changed, 1628 insertions(+), 44 deletions(-)
 create mode 100644 drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_uphy.c
 create mode 100644 drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_uphy.h

Comments

Andrew Lunn Nov. 10, 2022, 1:33 p.m. UTC | #1
On Wed, Nov 09, 2022 at 05:47:51PM -0500, David Thompson wrote:
> The BlueField-3 out-of-band Ethernet interface requires
> SerDes configuration. There are two aspects to this:
> 
> Configuration of PLL:
>     1) Initialize UPHY registers to values dependent on p1clk clock
>     2) Load PLL best known values via the gateway register
>     3) Set the fuses to tune up the SerDes voltage
>     4) Lock the PLL
>     5) Get the lanes out of functional reset.
>     6) Configure the UPHY microcontroller via gateway reads/writes
> 
> Configuration of lanes:
>     1) Configure and open TX lanes
>     2) Configure and open RX lanes

I still don't like all these black magic tables in the driver.

But lets see what others say.

    Andrew
Jakub Kicinski Nov. 12, 2022, 5:34 a.m. UTC | #2
On Thu, 10 Nov 2022 14:33:47 +0100 Andrew Lunn wrote:
> On Wed, Nov 09, 2022 at 05:47:51PM -0500, David Thompson wrote:
> > The BlueField-3 out-of-band Ethernet interface requires
> > SerDes configuration. There are two aspects to this:
> > 
> > Configuration of PLL:
> >     1) Initialize UPHY registers to values dependent on p1clk clock
> >     2) Load PLL best known values via the gateway register
> >     3) Set the fuses to tune up the SerDes voltage
> >     4) Lock the PLL
> >     5) Get the lanes out of functional reset.
> >     6) Configure the UPHY microcontroller via gateway reads/writes
> > 
> > Configuration of lanes:
> >     1) Configure and open TX lanes
> >     2) Configure and open RX lanes  
> 
> I still don't like all these black magic tables in the driver.
> 
> But lets see what others say.

Well, the patch was marked as Changes Requested so it seems that DaveM
concurs :) (I'm slightly desensitized to those tables because they
happen in WiFi relatively often.)

The recommendation is to come up with a format for a binary file, load
it via FW loader and then parse in the kernel?

We did have a recommendation against parsing FW files in the kernel at
some point, too, but perhaps this is simple enough to pass.

Should this be shared infra? The problem is fairly common.
Saeed Mahameed Nov. 12, 2022, 9:52 a.m. UTC | #3
On 11 Nov 21:34, Jakub Kicinski wrote:
>On Thu, 10 Nov 2022 14:33:47 +0100 Andrew Lunn wrote:
>> On Wed, Nov 09, 2022 at 05:47:51PM -0500, David Thompson wrote:
>> > The BlueField-3 out-of-band Ethernet interface requires
>> > SerDes configuration. There are two aspects to this:
>> >
>> > Configuration of PLL:
>> >     1) Initialize UPHY registers to values dependent on p1clk clock
>> >     2) Load PLL best known values via the gateway register
>> >     3) Set the fuses to tune up the SerDes voltage
>> >     4) Lock the PLL
>> >     5) Get the lanes out of functional reset.
>> >     6) Configure the UPHY microcontroller via gateway reads/writes
>> >
>> > Configuration of lanes:
>> >     1) Configure and open TX lanes
>> >     2) Configure and open RX lanes
>>
>> I still don't like all these black magic tables in the driver.
>>
>> But lets see what others say.
>
>Well, the patch was marked as Changes Requested so it seems that DaveM
>concurs :) (I'm slightly desensitized to those tables because they
>happen in WiFi relatively often.)
>
>The recommendation is to come up with a format for a binary file, load
>it via FW loader and then parse in the kernel?

By FW loader you mean request_firmware() functionality ?

I am not advocating for black magic tables of course :), but how do we
avoid them if request_firmware() will be an overkill to configure such a
simple device? Express such data in a developer friendly c structures
with somewhat sensible field names?

>
>We did have a recommendation against parsing FW files in the kernel at
>some point, too, but perhaps this is simple enough to pass.
>
>Should this be shared infra? The problem is fairly common.

Infrastructure to parse vendor Firmware ? we can't get vendors to agree on
ethtool interface, you want them to agree on one firmware format :)?

BTW i don't think the issue here is firmware at all, this is device
specific config space.
Andrew Lunn Nov. 12, 2022, 3:53 p.m. UTC | #4
> > The recommendation is to come up with a format for a binary file, load
> > it via FW loader and then parse in the kernel?
> 
> By FW loader you mean request_firmware() functionality ?
> 
> I am not advocating for black magic tables of course :), but how do we
> avoid them if request_firmware() will be an overkill to configure such a
> simple device? Express such data in a developer friendly c structures
> with somewhat sensible field names?

Do you think anybody other than your company has the ability to change
these values? Is there useful documentation about what they do, even
if it is under NDA? Why would somebody actually need to change them?

Is here functionally here which you don't support but the community
might like to add?

Expressing the data in a developer friendly C structure only really
make sense if there is a small collection of developers out there who
have the skills, documentation and maybe equipment to actually make
meaningful changes.

I don't like making it harder to some clever people to hack new stuff
into your drivers, but there are so few contributions from the
community to your drivers that it might as well be black magic, and
just load the values from a file.

       Andrew
Jakub Kicinski Nov. 15, 2022, 12:50 a.m. UTC | #5
On Sat, 12 Nov 2022 01:52:47 -0800 Saeed Mahameed wrote:
> >Well, the patch was marked as Changes Requested so it seems that DaveM
> >concurs :) (I'm slightly desensitized to those tables because they
> >happen in WiFi relatively often.)
> >
> >The recommendation is to come up with a format for a binary file, load
> >it via FW loader and then parse in the kernel?  
> 
> By FW loader you mean request_firmware() functionality ?

Yes, that's what I meant.

> I am not advocating for black magic tables of course :), but how do we
> avoid them if request_firmware() will be an overkill to configure such a
> simple device? Express such data in a developer friendly c structures
> with somewhat sensible field names?

I don't feel particularly strongly but seems like something worth
exploring. A minor advantage is that once the init is done the tables
can be discarded from memory.

> >We did have a recommendation against parsing FW files in the kernel at
> >some point, too, but perhaps this is simple enough to pass.
> >
> >Should this be shared infra? The problem is fairly common.  
> 
> Infrastructure to parse vendor Firmware ? we can't get vendors to agree on
> ethtool interface, you want them to agree on one firmware format :)?

We can keep the table format pretty much as is. What I had in mind was
basically creating a binary file format with u64 address, and u64 data.
Plus file sections to pack multiple tables into one file.
Pretty pleasant coding exercise if you ask me :)

> BTW i don't think the issue here is firmware at all, this is device
> specific config space.
Jakub Kicinski Nov. 15, 2022, 12:56 a.m. UTC | #6
On Sat, 12 Nov 2022 16:53:28 +0100 Andrew Lunn wrote:
> Do you think anybody other than your company has the ability to change
> these values? Is there useful documentation about what they do, even
> if it is under NDA? Why would somebody actually need to change them?
> 
> Is here functionally here which you don't support but the community
> might like to add?
> 
> Expressing the data in a developer friendly C structure only really
> make sense if there is a small collection of developers out there who
> have the skills, documentation and maybe equipment to actually make
> meaningful changes.

+1, even if the tables are not "FW as in compiled code" it's still 
"FW as in opaque blob". Plus if the format is well known and documented
modifying the files is not harder than changing the kernel.

I think the applicability would be much wider. I will definitely make
the WiFi people use this mechanism:

  drivers/net/wireless/realtek/rtw89/rtw8852a_table.c

ugh.

> I don't like making it harder to some clever people to hack new stuff
> into your drivers, but there are so few contributions from the
> community to your drivers that it might as well be black magic, and
> just load the values from a file.
Andrew Lunn Nov. 15, 2022, 1:06 a.m. UTC | #7
> I am not advocating for black magic tables of course :), but how do we
> > avoid them if request_firmware() will be an overkill to configure such a
> > simple device? Express such data in a developer friendly c structures
> > with somewhat sensible field names?
> 
> I don't feel particularly strongly but seems like something worth
> exploring. A minor advantage is that once the init is done the tables
> can be discarded from memory.

I wondered about that, but i'm not sure initdata works for modules,
and for hot pluggable devices like PCIe, you never know when another
one might appear and you need the tables.

    Andrew
Jakub Kicinski Nov. 15, 2022, 1:13 a.m. UTC | #8
On Tue, 15 Nov 2022 02:06:19 +0100 Andrew Lunn wrote:
>   > I am not advocating for black magic tables of course :), but how do we  
> > > avoid them if request_firmware() will be an overkill to configure such a
> > > simple device? Express such data in a developer friendly c structures
> > > with somewhat sensible field names?  
> > 
> > I don't feel particularly strongly but seems like something worth
> > exploring. A minor advantage is that once the init is done the tables
> > can be discarded from memory.  
> 
> I wondered about that, but i'm not sure initdata works for modules,
> and for hot pluggable devices like PCIe, you never know when another
> one might appear and you need the tables.

Right, I meant that the request_firmware() version can discard 
the tables. I shouldn't have said tables :)
Jakub Kicinski Nov. 16, 2022, 4:30 p.m. UTC | #9
On Mon, 14 Nov 2022 17:13:05 -0800 Jakub Kicinski wrote:
> On Tue, 15 Nov 2022 02:06:19 +0100 Andrew Lunn wrote:
> > > I don't feel particularly strongly but seems like something worth
> > > exploring. A minor advantage is that once the init is done the tables
> > > can be discarded from memory.    
> > 
> > I wondered about that, but i'm not sure initdata works for modules,
> > and for hot pluggable devices like PCIe, you never know when another
> > one might appear and you need the tables.  
> 
> Right, I meant that the request_firmware() version can discard 
> the tables. I shouldn't have said tables :)

Saeed, David, are you looking into this? The problem come up again 
in a Realtek USB conversation.

The task is so small and well defined I'm pretty sure I can get some
aspiring kernel developer at Meta to knock it off in a few days.

FWIW the structure of a file I had in mind would be something like this:

# Section 0 - strings (must be section 0)
 # header
 u32 type:   1   # string section
 u32 length: n   # length excluding header and pads
 u32 name:   0   # offset to the name in str section
 u32 pad:    0   # align to 8B
 # data
 .str\0table_abc\0table_def\0some_other_string\0
 # pad, align to 8B
 \0\0\0\0\0\0\0

# Section 1 - table_abc
 # header
 u32 type:   2   # 32b/32b table
 u32 length: 64  # length excluding header and pads
 u32 name:   5   # offset to the name in str section
 u32 pad:    0
 # data
 [ 0x210, 0xc00ff ]
 [ 0x214, 0xffeee ]
 [ 0x218, 0xdeaddd ]
 [ 0x21c, 0xc4ee5e ]
 [ 0x220, 0xc00ff ]
 [ 0x224, 0xffeee ]
 [ 0x228, 0xdeaddd ]
 [ 0x22c, 0xc4ee5e ]

etc.

Use:
	struct fw_table32 *abc, *def;

	fw = request_firmware("whatever_name.ftb");
	
	abc = fw_table_get(fw, "table_abc");
	/* use abc */

	def = fw_table_get(fw, "table_def");
	/* use def */

	release_firmware(fw)
Saeed Mahameed Nov. 17, 2022, 2:01 a.m. UTC | #10
On 16 Nov 08:30, Jakub Kicinski wrote:
>On Mon, 14 Nov 2022 17:13:05 -0800 Jakub Kicinski wrote:
>> On Tue, 15 Nov 2022 02:06:19 +0100 Andrew Lunn wrote:
>> > > I don't feel particularly strongly but seems like something worth
>> > > exploring. A minor advantage is that once the init is done the tables
>> > > can be discarded from memory.
>> >
>> > I wondered about that, but i'm not sure initdata works for modules,
>> > and for hot pluggable devices like PCIe, you never know when another
>> > one might appear and you need the tables.
>>
>> Right, I meant that the request_firmware() version can discard
>> the tables. I shouldn't have said tables :)
>
>Saeed, David, are you looking into this? The problem come up again
>in a Realtek USB conversation.
>
>The task is so small and well defined I'm pretty sure I can get some
>aspiring kernel developer at Meta to knock it off in a few days.
>

Give me a couple of days and will let you know what's the verdict.
I sent David and Asmaa the links to read up on Request Firmware. Still
waiting for a response.

>FWIW the structure of a file I had in mind would be something like this:
>
># Section 0 - strings (must be section 0)
> # header
> u32 type:   1   # string section
> u32 length: n   # length excluding header and pads
> u32 name:   0   # offset to the name in str section
> u32 pad:    0   # align to 8B
> # data
> .str\0table_abc\0table_def\0some_other_string\0
> # pad, align to 8B
> \0\0\0\0\0\0\0
>
># Section 1 - table_abc
> # header
> u32 type:   2   # 32b/32b table
> u32 length: 64  # length excluding header and pads
> u32 name:   5   # offset to the name in str section
> u32 pad:    0
> # data
> [ 0x210, 0xc00ff ]
> [ 0x214, 0xffeee ]
> [ 0x218, 0xdeaddd ]
> [ 0x21c, 0xc4ee5e ]
> [ 0x220, 0xc00ff ]
> [ 0x224, 0xffeee ]
> [ 0x228, 0xdeaddd ]
> [ 0x22c, 0xc4ee5e ]
>
>etc.
>
>Use:
>	struct fw_table32 *abc, *def;
>
>	fw = request_firmware("whatever_name.ftb");
>	
>	abc = fw_table_get(fw, "table_abc");
>	/* use abc */
>

abc is just a byte buffer ? right ?

>	def = fw_table_get(fw, "table_def");
>	/* use def */
>

And what goes here? any constraints on how the driver must interpret
and handle abc/def blobs ? 

>	release_firmware(fw)

What if the same abc blob structure/table format is used to setup dynamic link
properties, say via ethtool -s ? Then the whole request firmware will be
redundant since "struct abc {};" must be defined in the driver src code.

I like the idea, i am just trying to figure how we are going to define it
and how developers will differentiate between when to use this or when to
use standard APIs to setup their devices.
Jakub Kicinski Nov. 17, 2022, 6:23 a.m. UTC | #11
On Wed, 16 Nov 2022 18:01:41 -0800 Saeed Mahameed wrote:
> >	fw = request_firmware("whatever_name.ftb");
> >	
> >	abc = fw_table_get(fw, "table_abc");
> >	/* use abc */
> >  
> 
> abc is just a byte buffer ? right ?

pointer to const struct fw_table32, which is just;

struct fw_table32 {
	u32 addr;
	u32 value;
};

Actually we need the length as well, so perhaps this is better:

struct fw_table32 {
	u32 addr;
	u32 val;
};

struct fw_table_result {
	uint cnt;
	union {
		const struct fw_table32 *tb32;
	};
};

User:

	struct fw_table_result tab;

	fw = request_firmware("whatever_name.ftb");
	if (!fw)
		...

	err = fw_table_get(fw, "table_abc", &tab);
	if (err)
		...
	for (i = 0; i < tab.cnt; i++) /* use abc */
		write_or_whatever(hw, tab.tb32[i].addr, tab.tb32[i].val);

	def = fw_table_get(fw, "table_def");
	if (err)
		...
	for (i = 0; i < tab.cnt; i++) /* use def */
		write_or_whatever(hw, tab.tb32[i].addr, tab.tb32[i].val);

	release_firmware(fw)

> >	def = fw_table_get(fw, "table_def");
> >	/* use def */
> >  
> 
> And what goes here? any constraints on how the driver must interpret
> and handle abc/def blobs ? 

In the example I assumed a typical buffer with addr / value pairs.
But we can define more table types as needed.

> >	release_firmware(fw)  
> 
> What if the same abc blob structure/table format is used to setup dynamic link
> properties, say via ethtool -s ? Then the whole request firmware will be
> redundant since "struct abc {};" must be defined in the driver src code.

No complex structures, we'd be only targeting register init 
and small FW blobs (IOW { u32 addr; u32 val; } and { u8 val; }).
Stuff which Windows? drivers tend to put into the code as static array.

> I like the idea, i am just trying to figure how we are going to define it
> and how developers will differentiate between when to use this or when to
> use standard APIs to setup their devices.
diff mbox series

Patch

diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/Makefile b/drivers/net/ethernet/mellanox/mlxbf_gige/Makefile
index a97c2bef846b..524af17cad9c 100644
--- a/drivers/net/ethernet/mellanox/mlxbf_gige/Makefile
+++ b/drivers/net/ethernet/mellanox/mlxbf_gige/Makefile
@@ -7,4 +7,5 @@  mlxbf_gige-y := mlxbf_gige_ethtool.o \
 		mlxbf_gige_main.o \
 		mlxbf_gige_mdio.o \
 		mlxbf_gige_rx.o   \
-		mlxbf_gige_tx.o
+		mlxbf_gige_tx.o   \
+		mlxbf_gige_uphy.o
diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h
index a453b9cd9033..e9bd09ee0b1f 100644
--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h
+++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h
@@ -100,6 +100,7 @@  struct mlxbf_gige {
 	struct platform_device *pdev;
 	void __iomem *mdio_io;
 	void __iomem *clk_io;
+	void __iomem *fuse_gw_io;
 	struct mii_bus *mdiobus;
 	spinlock_t lock;      /* for packet processing indices */
 	u16 rx_q_entries;
@@ -166,7 +167,8 @@  enum mlxbf_gige_res {
 	MLXBF_GIGE_RES_GPIO0,
 	MLXBF_GIGE_RES_LLU,
 	MLXBF_GIGE_RES_PLU,
-	MLXBF_GIGE_RES_CLK
+	MLXBF_GIGE_RES_CLK,
+	MLXBF_GIGE_RES_FUSE_GW
 };
 
 /* Version of register data returned by mlxbf_gige_get_regs() */
diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c
index 32d7030eb2cf..80060a54ba95 100644
--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c
+++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c
@@ -18,6 +18,25 @@ 
 
 #include "mlxbf_gige.h"
 #include "mlxbf_gige_regs.h"
+#include "mlxbf_gige_uphy.h"
+
+#define MLXBF_GIGE_BF2_COREPLL_ADDR 0x02800c30
+#define MLXBF_GIGE_BF2_COREPLL_SIZE 0x0000000c
+#define MLXBF_GIGE_BF3_COREPLL_ADDR 0x13409824
+#define MLXBF_GIGE_BF3_COREPLL_SIZE 0x00000020
+
+static struct resource corepll_params[] = {
+	[MLXBF_GIGE_VERSION_BF2] = {
+		.start = MLXBF_GIGE_BF2_COREPLL_ADDR,
+		.end = MLXBF_GIGE_BF2_COREPLL_ADDR + MLXBF_GIGE_BF2_COREPLL_SIZE - 1,
+		.name = "COREPLL_RES"
+	},
+	[MLXBF_GIGE_VERSION_BF3] = {
+		.start = MLXBF_GIGE_BF3_COREPLL_ADDR,
+		.end = MLXBF_GIGE_BF3_COREPLL_ADDR + MLXBF_GIGE_BF3_COREPLL_SIZE - 1,
+		.name = "COREPLL_RES"
+	}
+};
 
 /* Allocate SKB whose payload pointer aligns with the Bluefield
  * hardware DMA limitation, i.e. DMA operation can't cross
@@ -360,11 +379,14 @@  static int mlxbf_gige_probe(struct platform_device *pdev)
 {
 	struct phy_device *phydev;
 	struct net_device *netdev;
+	struct resource *clk_res;
 	struct mlxbf_gige *priv;
 	void __iomem *llu_base;
 	void __iomem *plu_base;
+	void __iomem *clk_io;
 	void __iomem *base;
 	int addr, phy_irq;
+	u64 soc_version;
 	u64 control;
 	int err;
 
@@ -372,6 +394,25 @@  static int mlxbf_gige_probe(struct platform_device *pdev)
 	if (IS_ERR(base))
 		return PTR_ERR(base);
 
+	soc_version = readq(base + MLXBF_GIGE_VERSION);
+	if (soc_version > MLXBF_GIGE_VERSION_BF3)
+		return -ENODEV;
+
+	/* clk resource shared with other drivers so cannot use
+	 * devm_platform_ioremap_resource
+	 */
+	clk_res = platform_get_resource(pdev, IORESOURCE_MEM, MLXBF_GIGE_RES_CLK);
+	if (!clk_res) {
+		/* For backward compatibility with older ACPI tables, also keep
+		 * CLK resource internal to the driver.
+		 */
+		clk_res = &corepll_params[soc_version];
+	}
+
+	clk_io = devm_ioremap(&pdev->dev, clk_res->start, resource_size(clk_res));
+	if (!clk_io)
+		return -ENOMEM;
+
 	llu_base = devm_platform_ioremap_resource(pdev, MLXBF_GIGE_RES_LLU);
 	if (IS_ERR(llu_base))
 		return PTR_ERR(llu_base);
@@ -401,17 +442,23 @@  static int mlxbf_gige_probe(struct platform_device *pdev)
 
 	spin_lock_init(&priv->lock);
 
-	priv->hw_version = readq(base + MLXBF_GIGE_VERSION);
+	priv->clk_io = clk_io;
+	priv->base = base;
+	priv->llu_base = llu_base;
+	priv->plu_base = plu_base;
+	priv->hw_version = soc_version;
+
+	if (priv->hw_version == MLXBF_GIGE_VERSION_BF3) {
+		err = mlxbf_gige_config_uphy(priv);
+		if (err)
+			return err;
+	}
 
 	/* Attach MDIO device */
 	err = mlxbf_gige_mdio_probe(pdev, priv);
 	if (err)
 		return err;
 
-	priv->base = base;
-	priv->llu_base = llu_base;
-	priv->plu_base = plu_base;
-
 	priv->rx_q_entries = MLXBF_GIGE_DEFAULT_RXQ_SZ;
 	priv->tx_q_entries = MLXBF_GIGE_DEFAULT_TXQ_SZ;
 
diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c
index 7ac06fd31011..043edf57e36b 100644
--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c
+++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c
@@ -113,24 +113,6 @@  static struct mlxbf_gige_mdio_gw mlxbf_gige_mdio_gw_t[] = {
 /* Busy bit is set by software and cleared by hardware */
 #define MLXBF_GIGE_MDIO_SET_BUSY	0x1
 
-#define MLXBF_GIGE_BF2_COREPLL_ADDR 0x02800c30
-#define MLXBF_GIGE_BF2_COREPLL_SIZE 0x0000000c
-#define MLXBF_GIGE_BF3_COREPLL_ADDR 0x13409824
-#define MLXBF_GIGE_BF3_COREPLL_SIZE 0x00000010
-
-static struct resource corepll_params[] = {
-	[MLXBF_GIGE_VERSION_BF2] = {
-		.start = MLXBF_GIGE_BF2_COREPLL_ADDR,
-		.end = MLXBF_GIGE_BF2_COREPLL_ADDR + MLXBF_GIGE_BF2_COREPLL_SIZE - 1,
-		.name = "COREPLL_RES"
-	},
-	[MLXBF_GIGE_VERSION_BF3] = {
-		.start = MLXBF_GIGE_BF3_COREPLL_ADDR,
-		.end = MLXBF_GIGE_BF3_COREPLL_ADDR + MLXBF_GIGE_BF3_COREPLL_SIZE - 1,
-		.name = "COREPLL_RES"
-	}
-};
-
 /* Returns core clock i1clk in Hz */
 static u64 calculate_i1clk(struct mlxbf_gige *priv)
 {
@@ -294,31 +276,12 @@  static void mlxbf_gige_mdio_cfg(struct mlxbf_gige *priv)
 int mlxbf_gige_mdio_probe(struct platform_device *pdev, struct mlxbf_gige *priv)
 {
 	struct device *dev = &pdev->dev;
-	struct resource *res;
 	int ret;
 
-	if (priv->hw_version > MLXBF_GIGE_VERSION_BF3)
-		return -ENODEV;
-
 	priv->mdio_io = devm_platform_ioremap_resource(pdev, MLXBF_GIGE_RES_MDIO9);
 	if (IS_ERR(priv->mdio_io))
 		return PTR_ERR(priv->mdio_io);
 
-	/* clk resource shared with other drivers so cannot use
-	 * devm_platform_ioremap_resource
-	 */
-	res = platform_get_resource(pdev, IORESOURCE_MEM, MLXBF_GIGE_RES_CLK);
-	if (!res) {
-		/* For backward compatibility with older ACPI tables, also keep
-		 * CLK resource internal to the driver.
-		 */
-		res = &corepll_params[priv->hw_version];
-	}
-
-	priv->clk_io = devm_ioremap(dev, res->start, resource_size(res));
-	if (!priv->clk_io)
-		return -ENOMEM;
-
 	priv->mdio_gw = &mlxbf_gige_mdio_gw_t[priv->hw_version];
 
 	mlxbf_gige_mdio_cfg(priv);
diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_uphy.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_uphy.c
new file mode 100644
index 000000000000..eb8c55b135a9
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_uphy.c
@@ -0,0 +1,1173 @@ 
+// SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause
+
+/* UPHY support for Nvidia Gigabit Ethernet driver
+ *
+ * Copyright (C) 2022 NVIDIA CORPORATION & AFFILIATES
+ */
+
+#include <linux/bitfield.h>
+#include <linux/iopoll.h>
+#include <linux/platform_device.h>
+
+#include "mlxbf_gige.h"
+#include "mlxbf_gige_uphy.h"
+
+static const struct mlxbf_gige_uphy_cfg_reg
+mlxbf_gige_clm_init[] = {
+	{.addr = 0x001, .wdata = 0x0105},
+	{.addr = 0x008, .wdata = 0x0001},
+	{.addr = 0x00B, .wdata = 0x8420},
+	{.addr = 0x00E, .wdata = 0x0110},
+	{.addr = 0x010, .wdata = 0x3010},
+	{.addr = 0x027, .wdata = 0x0104},
+	{.addr = 0x02F, .wdata = 0x09EA},
+	{.addr = 0x055, .wdata = 0x0008},
+	{.addr = 0x058, .wdata = 0x0088},
+	{.addr = 0x072, .wdata = 0x3222},
+	{.addr = 0x073, .wdata = 0x7654},
+	{.addr = 0x074, .wdata = 0xBA98},
+	{.addr = 0x075, .wdata = 0xDDDC}
+};
+
+static const struct mlxbf_gige_uphy_cfg_reg
+mlxbf_gige_dlm_imem_init[] = {
+	{.addr = 0x39C, .wdata = 0x0000},
+	{.addr = 0x39D, .wdata = 0x0095},
+	{.addr = 0x3BF, .wdata = 0x9027},
+	{.addr = 0x39E, .wdata = 0xA8F6},
+	{.addr = 0x39F, .wdata = 0xAA10},
+	{.addr = 0x3A0, .wdata = 0xA8D4},
+	{.addr = 0x3A1, .wdata = 0xA7AE},
+	{.addr = 0x3A2, .wdata = 0xA7CC},
+	{.addr = 0x3A3, .wdata = 0x9BE4},
+	{.addr = 0x3A4, .wdata = 0xB2D2},
+	{.addr = 0x3A5, .wdata = 0xB1F2},
+	{.addr = 0x3AE, .wdata = 0x7C38},
+	{.addr = 0x3AF, .wdata = 0x7C4A},
+	{.addr = 0x3B0, .wdata = 0x7C25},
+	{.addr = 0x3B1, .wdata = 0x7C74},
+	{.addr = 0x3B2, .wdata = 0x3C00},
+	{.addr = 0x3B3, .wdata = 0x3C11},
+	{.addr = 0x3B4, .wdata = 0x3C5D},
+	{.addr = 0x3B5, .wdata = 0x3C5D}
+};
+
+static const struct mlxbf_gige_uphy_cfg_reg
+mlxbf_gige_dlm_seq_imem_wr_en_init = {
+	.addr = 0x39A, .wdata = 0x0001
+};
+
+static const struct mlxbf_gige_uphy_cfg_reg
+mlxbf_gige_dlm_seq_imem_wr_dis_init = {
+	.addr = 0x39A, .wdata = 0x0000
+};
+
+static const struct mlxbf_gige_uphy_cfg_reg
+mlxbf_gige_dlm_imem_data[] = {
+	{ /* .iaddr = 0x0000 */ .wdata = 0x02DF},
+	{ /* .iaddr = 0x0001 */ .wdata = 0xEEC0},
+	{ /* .iaddr = 0x0002 */ .wdata = 0xD508},
+	{ /* .iaddr = 0x0003 */ .wdata = 0x022F},
+	{ /* .iaddr = 0x0004 */ .wdata = 0xC401},
+	{ /* .iaddr = 0x0005 */ .wdata = 0xD341},
+	{ /* .iaddr = 0x0006 */ .wdata = 0xC402},
+	{ /* .iaddr = 0x0007 */ .wdata = 0xD342},
+	{ /* .iaddr = 0x0008 */ .wdata = 0xC403},
+	{ /* .iaddr = 0x0009 */ .wdata = 0xD343},
+	{ /* .iaddr = 0x000A */ .wdata = 0xC404},
+	{ /* .iaddr = 0x000B */ .wdata = 0xD344},
+	{ /* .iaddr = 0x000C */ .wdata = 0xC417},
+	{ /* .iaddr = 0x000D */ .wdata = 0xD355},
+	{ /* .iaddr = 0x000E */ .wdata = 0xC418},
+	{ /* .iaddr = 0x000F */ .wdata = 0xD356},
+	{ /* .iaddr = 0x0010 */ .wdata = 0xF021},
+	{ /* .iaddr = 0x0011 */ .wdata = 0xF003},
+	{ /* .iaddr = 0x0012 */ .wdata = 0xE224},
+	{ /* .iaddr = 0x0013 */ .wdata = 0x0DA9},
+	{ /* .iaddr = 0x0014 */ .wdata = 0xF003},
+	{ /* .iaddr = 0x0015 */ .wdata = 0xE21C},
+	{ /* .iaddr = 0x0016 */ .wdata = 0xEEC1},
+	{ /* .iaddr = 0x0017 */ .wdata = 0x0D87},
+	{ /* .iaddr = 0x0018 */ .wdata = 0xEEC1},
+	{ /* .iaddr = 0x0019 */ .wdata = 0xE806},
+	{ /* .iaddr = 0x001A */ .wdata = 0xC3C5},
+	{ /* .iaddr = 0x001B */ .wdata = 0xD306},
+	{ /* .iaddr = 0x001C */ .wdata = 0xEEDF},
+	{ /* .iaddr = 0x001D */ .wdata = 0xE806},
+	{ /* .iaddr = 0x001E */ .wdata = 0xC3C6},
+	{ /* .iaddr = 0x001F */ .wdata = 0xD306},
+	{ /* .iaddr = 0x0020 */ .wdata = 0xF002},
+	{ /* .iaddr = 0x0021 */ .wdata = 0xC3C8},
+	{ /* .iaddr = 0x0022 */ .wdata = 0x409A},
+	{ /* .iaddr = 0x0023 */ .wdata = 0xF021},
+	{ /* .iaddr = 0x0024 */ .wdata = 0xEEE0},
+	{ /* .iaddr = 0x0025 */ .wdata = 0xEEC0},
+	{ /* .iaddr = 0x0026 */ .wdata = 0xD70D},
+	{ /* .iaddr = 0x0027 */ .wdata = 0xC305},
+	{ /* .iaddr = 0x0028 */ .wdata = 0xD328},
+	{ /* .iaddr = 0x0029 */ .wdata = 0xC300},
+	{ /* .iaddr = 0x002A */ .wdata = 0xD314},
+	{ /* .iaddr = 0x002B */ .wdata = 0xC301},
+	{ /* .iaddr = 0x002C */ .wdata = 0xD318},
+	{ /* .iaddr = 0x002D */ .wdata = 0xC303},
+	{ /* .iaddr = 0x002E */ .wdata = 0xD320},
+	{ /* .iaddr = 0x002F */ .wdata = 0xC302},
+	{ /* .iaddr = 0x0030 */ .wdata = 0xD31C},
+	{ /* .iaddr = 0x0031 */ .wdata = 0xC304},
+	{ /* .iaddr = 0x0032 */ .wdata = 0xD324},
+	{ /* .iaddr = 0x0033 */ .wdata = 0xC358},
+	{ /* .iaddr = 0x0034 */ .wdata = 0xD330},
+	{ /* .iaddr = 0x0035 */ .wdata = 0xC307},
+	{ /* .iaddr = 0x0036 */ .wdata = 0xD115},
+	{ /* .iaddr = 0x0037 */ .wdata = 0xF021},
+	{ /* .iaddr = 0x0038 */ .wdata = 0xD70D},
+	{ /* .iaddr = 0x0039 */ .wdata = 0xC305},
+	{ /* .iaddr = 0x003A */ .wdata = 0xD328},
+	{ /* .iaddr = 0x003B */ .wdata = 0xC300},
+	{ /* .iaddr = 0x003C */ .wdata = 0xD314},
+	{ /* .iaddr = 0x003D */ .wdata = 0xC301},
+	{ /* .iaddr = 0x003E */ .wdata = 0xD318},
+	{ /* .iaddr = 0x003F */ .wdata = 0xC303},
+	{ /* .iaddr = 0x0040 */ .wdata = 0xD320},
+	{ /* .iaddr = 0x0041 */ .wdata = 0xC302},
+	{ /* .iaddr = 0x0042 */ .wdata = 0xD31C},
+	{ /* .iaddr = 0x0043 */ .wdata = 0xC304},
+	{ /* .iaddr = 0x0044 */ .wdata = 0xD324},
+	{ /* .iaddr = 0x0045 */ .wdata = 0xC358},
+	{ /* .iaddr = 0x0046 */ .wdata = 0xD330},
+	{ /* .iaddr = 0x0047 */ .wdata = 0xC307},
+	{ /* .iaddr = 0x0048 */ .wdata = 0xD115},
+	{ /* .iaddr = 0x0049 */ .wdata = 0xF021},
+	{ /* .iaddr = 0x004A */ .wdata = 0xC70D},
+	{ /* .iaddr = 0x004B */ .wdata = 0xD70F},
+	{ /* .iaddr = 0x004C */ .wdata = 0xC328},
+	{ /* .iaddr = 0x004D */ .wdata = 0xD305},
+	{ /* .iaddr = 0x004E */ .wdata = 0xC314},
+	{ /* .iaddr = 0x004F */ .wdata = 0xD300},
+	{ /* .iaddr = 0x0050 */ .wdata = 0xC318},
+	{ /* .iaddr = 0x0051 */ .wdata = 0xD301},
+	{ /* .iaddr = 0x0052 */ .wdata = 0xC320},
+	{ /* .iaddr = 0x0053 */ .wdata = 0xD303},
+	{ /* .iaddr = 0x0054 */ .wdata = 0xC31C},
+	{ /* .iaddr = 0x0055 */ .wdata = 0xD302},
+	{ /* .iaddr = 0x0056 */ .wdata = 0xC324},
+	{ /* .iaddr = 0x0057 */ .wdata = 0xD304},
+	{ /* .iaddr = 0x0058 */ .wdata = 0xC330},
+	{ /* .iaddr = 0x0059 */ .wdata = 0xD358},
+	{ /* .iaddr = 0x005A */ .wdata = 0xC115},
+	{ /* .iaddr = 0x005B */ .wdata = 0xD307},
+	{ /* .iaddr = 0x005C */ .wdata = 0xF021},
+	{ /* .iaddr = 0x005D */ .wdata = 0x0249},
+	{ /* .iaddr = 0x005E */ .wdata = 0x0362},
+	{ /* .iaddr = 0x005F */ .wdata = 0x023D},
+	{ /* .iaddr = 0x0060 */ .wdata = 0xEEC1},
+	{ /* .iaddr = 0x0061 */ .wdata = 0x0369},
+	{ /* .iaddr = 0x0062 */ .wdata = 0xEEC1},
+	{ /* .iaddr = 0x0063 */ .wdata = 0x0CEA},
+	{ /* .iaddr = 0x0064 */ .wdata = 0xEEC2},
+	{ /* .iaddr = 0x0065 */ .wdata = 0xD701},
+	{ /* .iaddr = 0x0066 */ .wdata = 0x02C8},
+	{ /* .iaddr = 0x0067 */ .wdata = 0xC3C3},
+	{ /* .iaddr = 0x0068 */ .wdata = 0xD306},
+	{ /* .iaddr = 0x0069 */ .wdata = 0xC3C8},
+	{ /* .iaddr = 0x006A */ .wdata = 0x009A},
+	{ /* .iaddr = 0x006B */ .wdata = 0xC3D1},
+	{ /* .iaddr = 0x006C */ .wdata = 0xD309},
+	{ /* .iaddr = 0x006D */ .wdata = 0x0C46},
+	{ /* .iaddr = 0x006E */ .wdata = 0x0DE7},
+	{ /* .iaddr = 0x006F */ .wdata = 0xEEC0},
+	{ /* .iaddr = 0x0070 */ .wdata = 0xC3D9},
+	{ /* .iaddr = 0x0071 */ .wdata = 0x0DDE},
+	{ /* .iaddr = 0x0072 */ .wdata = 0x02D7},
+	{ /* .iaddr = 0x0073 */ .wdata = 0xF021},
+	{ /* .iaddr = 0x0074 */ .wdata = 0x1441},
+	{ /* .iaddr = 0x0075 */ .wdata = 0xF003},
+	{ /* .iaddr = 0x0076 */ .wdata = 0xC03F},
+	{ /* .iaddr = 0x0077 */ .wdata = 0xF704},
+	{ /* .iaddr = 0x0078 */ .wdata = 0xF009},
+	{ /* .iaddr = 0x0079 */ .wdata = 0xE21A},
+	{ /* .iaddr = 0x007A */ .wdata = 0xF002},
+	{ /* .iaddr = 0x007B */ .wdata = 0x0C52},
+	{ /* .iaddr = 0x007C */ .wdata = 0xE206},
+	{ /* .iaddr = 0x007D */ .wdata = 0xEEC1},
+	{ /* .iaddr = 0x007E */ .wdata = 0xD01A},
+	{ /* .iaddr = 0x007F */ .wdata = 0x3C5D},
+	{ /* .iaddr = 0x0080 */ .wdata = 0xEEC0},
+	{ /* .iaddr = 0x0081 */ .wdata = 0xD01A},
+	{ /* .iaddr = 0x0082 */ .wdata = 0x0E12},
+	{ /* .iaddr = 0x0083 */ .wdata = 0xEEC0},
+	{ /* .iaddr = 0x0084 */ .wdata = 0x13E1},
+	{ /* .iaddr = 0x0085 */ .wdata = 0x1441},
+	{ /* .iaddr = 0x0086 */ .wdata = 0xEEC1},
+	{ /* .iaddr = 0x0087 */ .wdata = 0xD70E},
+	{ /* .iaddr = 0x0088 */ .wdata = 0xD70F},
+	{ /* .iaddr = 0x0089 */ .wdata = 0xEEC0},
+	{ /* .iaddr = 0x008A */ .wdata = 0xD70E},
+	{ /* .iaddr = 0x008B */ .wdata = 0xC458},
+	{ /* .iaddr = 0x008C */ .wdata = 0x13BE},
+	{ /* .iaddr = 0x008D */ .wdata = 0xEEC0},
+	{ /* .iaddr = 0x008E */ .wdata = 0xF29B},
+	{ /* .iaddr = 0x008F */ .wdata = 0xE20A},
+	{ /* .iaddr = 0x0090 */ .wdata = 0xEEC1},
+	{ /* .iaddr = 0x0091 */ .wdata = 0xD01D},
+	{ /* .iaddr = 0x0092 */ .wdata = 0xEEC1},
+	{ /* .iaddr = 0x0093 */ .wdata = 0xD3FD},
+	{ /* .iaddr = 0x0094 */ .wdata = 0xF021}
+};
+
+static const struct mlxbf_gige_uphy_cfg_reg
+mlxbf_gige_dlm_seq_imem_csum_en = {
+	.addr = 0x39A, .wdata = 0x0004
+};
+
+static const struct mlxbf_gige_uphy_cfg_reg
+mlxbf_gige_dlm_seq_imem_csum_dis = {
+	.addr = 0x39A, .wdata = 0x0000
+};
+
+static const struct mlxbf_gige_uphy_cfg_reg
+mlxbf_gige_dlm_seq_imem_bmap_clr[] = {
+	{.addr = 0x39E, .wdata = 0x0000},
+	{.addr = 0x39F, .wdata = 0x0000},
+	{.addr = 0x3A0, .wdata = 0x0000},
+	{.addr = 0x3A1, .wdata = 0x0000},
+	{.addr = 0x3A2, .wdata = 0x0000},
+	{.addr = 0x3A3, .wdata = 0x0000},
+	{.addr = 0x3A4, .wdata = 0x0000},
+	{.addr = 0x3A5, .wdata = 0x0000},
+	{.addr = 0x3A6, .wdata = 0x0000},
+	{.addr = 0x3A7, .wdata = 0x0000},
+	{.addr = 0x3A8, .wdata = 0x0000},
+	{.addr = 0x3A9, .wdata = 0x0000},
+	{.addr = 0x3AA, .wdata = 0x0000},
+	{.addr = 0x3AB, .wdata = 0x0000},
+	{.addr = 0x3AC, .wdata = 0x0000},
+	{.addr = 0x3AD, .wdata = 0x0000},
+	{.addr = 0x3AE, .wdata = 0x0000},
+	{.addr = 0x3AF, .wdata = 0x0000},
+	{.addr = 0x3B0, .wdata = 0x0000},
+	{.addr = 0x3B1, .wdata = 0x0000},
+	{.addr = 0x3B2, .wdata = 0x0000},
+	{.addr = 0x3B3, .wdata = 0x0000},
+	{.addr = 0x3B4, .wdata = 0x0000},
+	{.addr = 0x3B5, .wdata = 0x0000},
+	{.addr = 0x3B6, .wdata = 0x0000},
+	{.addr = 0x3B7, .wdata = 0x0000},
+	{.addr = 0x3B8, .wdata = 0x0000},
+	{.addr = 0x3B9, .wdata = 0x0000},
+	{.addr = 0x3BA, .wdata = 0x0000},
+	{.addr = 0x3BB, .wdata = 0x0000},
+	{.addr = 0x3BC, .wdata = 0x0000},
+	{.addr = 0x3BD, .wdata = 0x0000}
+};
+
+static const struct mlxbf_gige_uphy_cfg_reg
+mlxbf_gige_dlm_tx_init[] = {
+	{.addr = 0x002, .wdata = 0x5125},
+	{.addr = 0x01C, .wdata = 0x0018},
+	{.addr = 0x01E, .wdata = 0x0E00},
+	{.addr = 0x01F, .wdata = 0xC200},
+	{.addr = 0x023, .wdata = 0x0277},
+	{.addr = 0x024, .wdata = 0x026B},
+	{.addr = 0x053, .wdata = 0x0700},
+	{.addr = 0x059, .wdata = 0x1011},
+	{.addr = 0x060, .wdata = 0x0000},
+	{.addr = 0x062, .wdata = 0x0135},
+	{.addr = 0x063, .wdata = 0x0443},
+	{.addr = 0x064, .wdata = 0x0000},
+	{.addr = 0x066, .wdata = 0x0061},
+	{.addr = 0x067, .wdata = 0x0042},
+	{.addr = 0x06A, .wdata = 0x1212},
+	{.addr = 0x06B, .wdata = 0x1515},
+	{.addr = 0x06C, .wdata = 0x011A},
+	{.addr = 0x06D, .wdata = 0x0132},
+	{.addr = 0x06E, .wdata = 0x0632},
+	{.addr = 0x06F, .wdata = 0x0643},
+	{.addr = 0x070, .wdata = 0x0233},
+	{.addr = 0x071, .wdata = 0x0433},
+	{.addr = 0x07E, .wdata = 0x6A08},
+	{.addr = 0x08D, .wdata = 0x2101},
+	{.addr = 0x093, .wdata = 0x0015},
+	{.addr = 0x096, .wdata = 0x7555},
+	{.addr = 0x0A9, .wdata = 0xE754},
+	{.addr = 0x0AA, .wdata = 0x7ED1},
+	{.addr = 0x3FF, .wdata = 0x0000},
+	{.addr = 0x3FF, .wdata = 0x0000},
+	{.addr = 0x3FF, .wdata = 0x0000},
+	{.addr = 0x3FF, .wdata = 0x0000},
+	{.addr = 0x3FF, .wdata = 0x0000},
+	{.addr = 0x3FF, .wdata = 0x0000},
+	{.addr = 0x3FF, .wdata = 0x0000},
+	{.addr = 0x3FF, .wdata = 0x0000},
+	{.addr = 0x3FF, .wdata = 0x0000},
+	{.addr = 0x3FF, .wdata = 0x0000},
+	{.addr = 0x3FF, .wdata = 0x0000},
+	{.addr = 0x3FF, .wdata = 0x0000}
+};
+
+static const struct mlxbf_gige_uphy_cfg_reg
+mlxbf_gige_dlm_rx_init[] = {
+	{.addr = 0x003, .wdata = 0x5125},
+	{.addr = 0x01D, .wdata = 0x0004},
+	{.addr = 0x028, .wdata = 0x1000},
+	{.addr = 0x029, .wdata = 0x1001},
+	{.addr = 0x02E, .wdata = 0x0004},
+	{.addr = 0x053, .wdata = 0x0700},
+	{.addr = 0x057, .wdata = 0x5044},
+	{.addr = 0x05B, .wdata = 0x1011},
+	{.addr = 0x0D2, .wdata = 0x0002},
+	{.addr = 0x0D9, .wdata = 0x0000},
+	{.addr = 0x0DA, .wdata = 0x0000},
+	{.addr = 0x0DB, .wdata = 0x0000},
+	{.addr = 0x0E2, .wdata = 0x0000},
+	{.addr = 0x0E7, .wdata = 0xBB10},
+	{.addr = 0x0E8, .wdata = 0xBB10},
+	{.addr = 0x0EC, .wdata = 0x0111},
+	{.addr = 0x0ED, .wdata = 0x1C00},
+	{.addr = 0x0F5, .wdata = 0x0000},
+	{.addr = 0x102, .wdata = 0x0CA6},
+	{.addr = 0x107, .wdata = 0x0020},
+	{.addr = 0x10C, .wdata = 0x1E31},
+	{.addr = 0x10D, .wdata = 0x1D29},
+	{.addr = 0x111, .wdata = 0x00E7},
+	{.addr = 0x112, .wdata = 0x5202},
+	{.addr = 0x117, .wdata = 0x0493},
+	{.addr = 0x11B, .wdata = 0x0148},
+	{.addr = 0x120, .wdata = 0x23DE},
+	{.addr = 0x121, .wdata = 0x2294},
+	{.addr = 0x125, .wdata = 0x03FF},
+	{.addr = 0x126, .wdata = 0x25F0},
+	{.addr = 0x12B, .wdata = 0xC633},
+	{.addr = 0x136, .wdata = 0x0F6A},
+	{.addr = 0x143, .wdata = 0x0000},
+	{.addr = 0x148, .wdata = 0x0001},
+	{.addr = 0x14E, .wdata = 0x0000},
+	{.addr = 0x155, .wdata = 0x2003},
+	{.addr = 0x15C, .wdata = 0x099B},
+	{.addr = 0x161, .wdata = 0x0088},
+	{.addr = 0x16B, .wdata = 0x0433},
+	{.addr = 0x172, .wdata = 0x099B},
+	{.addr = 0x17C, .wdata = 0x045D},
+	{.addr = 0x17D, .wdata = 0x006A},
+	{.addr = 0x181, .wdata = 0x0000},
+	{.addr = 0x189, .wdata = 0x1590},
+	{.addr = 0x18E, .wdata = 0x0080},
+	{.addr = 0x18F, .wdata = 0x90EC},
+	{.addr = 0x191, .wdata = 0x79F8},
+	{.addr = 0x194, .wdata = 0x000A},
+	{.addr = 0x195, .wdata = 0x000A},
+	{.addr = 0x1EB, .wdata = 0x0133},
+	{.addr = 0x1F0, .wdata = 0x0030},
+	{.addr = 0x1F1, .wdata = 0x0030},
+	{.addr = 0x1F5, .wdata = 0x3737},
+	{.addr = 0x1F6, .wdata = 0x3737},
+	{.addr = 0x1FA, .wdata = 0x2C00},
+	{.addr = 0x1FF, .wdata = 0x0516},
+	{.addr = 0x200, .wdata = 0x0516},
+	{.addr = 0x204, .wdata = 0x3010},
+	{.addr = 0x209, .wdata = 0x0429},
+	{.addr = 0x20E, .wdata = 0x0010},
+	{.addr = 0x213, .wdata = 0x005A},
+	{.addr = 0x214, .wdata = 0x0000},
+	{.addr = 0x216, .wdata = 0x0000},
+	{.addr = 0x218, .wdata = 0x0000},
+	{.addr = 0x225, .wdata = 0x0000},
+	{.addr = 0x22A, .wdata = 0x0000},
+	{.addr = 0x22B, .wdata = 0x0000},
+	{.addr = 0x231, .wdata = 0x0000},
+	{.addr = 0x232, .wdata = 0x0000},
+	{.addr = 0x233, .wdata = 0x0000},
+	{.addr = 0x245, .wdata = 0x0300},
+	{.addr = 0x24A, .wdata = 0x0000},
+	{.addr = 0x24F, .wdata = 0xFFF3},
+	{.addr = 0x254, .wdata = 0x0000},
+	{.addr = 0x259, .wdata = 0x0000},
+	{.addr = 0x25E, .wdata = 0x0000},
+	{.addr = 0x265, .wdata = 0x0009},
+	{.addr = 0x267, .wdata = 0x0174},
+	{.addr = 0x271, .wdata = 0x01F0},
+	{.addr = 0x273, .wdata = 0x0170},
+	{.addr = 0x275, .wdata = 0x7828},
+	{.addr = 0x279, .wdata = 0x3E3A},
+	{.addr = 0x27D, .wdata = 0x8468},
+	{.addr = 0x283, .wdata = 0x000C},
+	{.addr = 0x285, .wdata = 0x7777},
+	{.addr = 0x288, .wdata = 0x5503},
+	{.addr = 0x28C, .wdata = 0x0030},
+	{.addr = 0x28E, .wdata = 0xBBBB},
+	{.addr = 0x290, .wdata = 0xBBBB},
+	{.addr = 0x293, .wdata = 0x0021},
+	{.addr = 0x2FA, .wdata = 0x3B40},
+	{.addr = 0x2FB, .wdata = 0x7777},
+	{.addr = 0x30A, .wdata = 0x8022},
+	{.addr = 0x319, .wdata = 0x205E},
+	{.addr = 0x31B, .wdata = 0x0000},
+	{.addr = 0x31D, .wdata = 0x6004},
+	{.addr = 0x320, .wdata = 0x3014},
+	{.addr = 0x322, .wdata = 0x6004},
+	{.addr = 0x326, .wdata = 0x6004},
+	{.addr = 0x32A, .wdata = 0x5000},
+	{.addr = 0x32E, .wdata = 0x5000},
+	{.addr = 0x332, .wdata = 0x6004},
+	{.addr = 0x336, .wdata = 0x6063},
+	{.addr = 0x389, .wdata = 0x0310},
+	{.addr = 0x3FF, .wdata = 0x0000},
+	{.addr = 0x3FF, .wdata = 0x0000},
+	{.addr = 0x3FF, .wdata = 0x0000},
+	{.addr = 0x3FF, .wdata = 0x0000},
+	{.addr = 0x3FF, .wdata = 0x0000},
+	{.addr = 0x3FF, .wdata = 0x0000},
+	{.addr = 0x3FF, .wdata = 0x0000},
+	{.addr = 0x3FF, .wdata = 0x0000},
+	{.addr = 0x3FF, .wdata = 0x0000},
+	{.addr = 0x3FF, .wdata = 0x0000},
+	{.addr = 0x3FF, .wdata = 0x0000},
+	{.addr = 0x3FF, .wdata = 0x0000},
+	{.addr = 0x3FF, .wdata = 0x0000},
+	{.addr = 0x3FF, .wdata = 0x0000},
+	{.addr = 0x3FF, .wdata = 0x0000},
+	{.addr = 0x3FF, .wdata = 0x0000}
+};
+
+/* returns plu clock p1clk in Hz */
+static u64 mlxbf_gige_calculate_p1clk(struct mlxbf_gige *priv)
+{
+	u8 core_od, core_r;
+	u64 freq_output;
+	u32 reg1, reg2;
+	u32 core_f;
+
+	reg1 = readl(priv->clk_io + MLXBF_GIGE_P1CLK_REG1);
+	reg2 = readl(priv->clk_io + MLXBF_GIGE_P1CLK_REG2);
+
+	core_f = (reg1 & MLXBF_GIGE_P1_CORE_F_MASK) >>
+		MLXBF_GIGE_P1_CORE_F_SHIFT;
+	core_r = (reg1 & MLXBF_GIGE_P1_CORE_R_MASK) >>
+		MLXBF_GIGE_P1_CORE_R_SHIFT;
+	core_od = (reg2 & MLXBF_GIGE_P1_CORE_OD_MASK) >>
+		MLXBF_GIGE_P1_CORE_OD_SHIFT;
+
+	/* Compute PLL output frequency as follow:
+	 *
+	 *                                     CORE_F / 16384
+	 * freq_output = freq_reference * ----------------------------
+	 *                              (CORE_R + 1) * (CORE_OD + 1)
+	 */
+	freq_output = div_u64(MLXBF_GIGE_P1_FREQ_REFERENCE * core_f,
+			      MLXBF_GIGE_P1_CLK_CONST);
+	freq_output = div_u64(freq_output, (core_r + 1) * (core_od + 1));
+
+	return freq_output;
+}
+
+static void mlxbf_gige_ugl_static_config(struct mlxbf_gige *priv)
+{
+	u32 val, p1clk_mhz;
+	u32 const_factor;
+	u64 p1clk;
+
+	/* p1clk is the PLU clock in Hz */
+	p1clk = mlxbf_gige_calculate_p1clk(priv);
+
+	/* get p1clk in MHz */
+	p1clk_mhz = div_u64(p1clk, 1000000);
+
+	/* Multiply the p1clk clock by 12 according to HW requirements */
+	const_factor = p1clk_mhz * MLXBF_GIGE_P1CLK_MULT_FACTOR;
+
+	/* ugl_cr_bridge_desc */
+	val = readl(priv->plu_base + MLXBF_GIGE_UGL_CR_BRIDGE_DESC);
+	val &= ~MLXBF_GIGE_UGL_CR_BRIDGE_ALL_MASK;
+	val |= FIELD_PREP(MLXBF_GIGE_UGL_CR_BRIDGE_SETUP_MASK,
+			  MLXBF_GIGE_UGL_CR_BRIDGE_SETUP_VAL(const_factor));
+	val |= FIELD_PREP(MLXBF_GIGE_UGL_CR_BRIDGE_PULSE_MASK,
+			  MLXBF_GIGE_UGL_CR_BRIDGE_PULSE_VAL(const_factor));
+	val |= FIELD_PREP(MLXBF_GIGE_UGL_CR_BRIDGE_HOLD_MASK,
+			  MLXBF_GIGE_UGL_CR_BRIDGE_HOLD_VAL(const_factor));
+	writel(val, priv->plu_base + MLXBF_GIGE_UGL_CR_BRIDGE_DESC);
+
+	/* pll1x_fsm_counters */
+	val = MLXBF_GIGE_PLL1X_FSM_DEFAULT_VAL(const_factor);
+	writel(val, priv->plu_base + MLXBF_GIGE_PLL1X_FSM_DEFAULT_CYCLES);
+
+	val = MLXBF_GIGE_PLL1X_FSM_SLEEP_VAL(const_factor);
+	writel(val, priv->plu_base + MLXBF_GIGE_PLL1X_FSM_SLEEP_CYCLES);
+
+	val = MLXBF_GIGE_PLL1X_FSM_RCAL_FLOW_VAL(const_factor);
+	writel(val, priv->plu_base + MLXBF_GIGE_PLL1X_FSM_RCAL_FLOW_CYCLES);
+
+	val = MLXBF_GIGE_PLL1X_FSM_CAL_FLOW_VAL(const_factor);
+	writel(val, priv->plu_base + MLXBF_GIGE_PLL1X_FSM_CAL_FLOW_CYCLES);
+
+	val = readl(priv->plu_base + MLXBF_GIGE_PLL1X_FSM_LOCKDET_STS_CYCLES);
+	val &= ~MLXBF_GIGE_PLL1X_FSM_LOCKDET_STS_MASK;
+	val |= FIELD_PREP(MLXBF_GIGE_PLL1X_FSM_LOCKDET_STS_MASK,
+			  MLXBF_GIGE_PLL1X_FSM_LOCKDET_STS_VAL(const_factor));
+	writel(val, priv->plu_base + MLXBF_GIGE_PLL1X_FSM_LOCKDET_STS_CYCLES);
+
+	/* tx_fsm_counters */
+	val = MLXBF_GIGE_TX_FSM_DEFAULT_VAL(const_factor);
+	writel(val, priv->plu_base + MLXBF_GIGE_TX_FSM_DEFAULT_CYCLES);
+
+	val = MLXBF_GIGE_TX_FSM_SLEEP_VAL(const_factor);
+	writel(val, priv->plu_base + MLXBF_GIGE_TX_FSM_SLEEP_CYCLES);
+
+	val = MLXBF_GIGE_TX_FSM_POWERUP_VAL(const_factor);
+	writel(val, priv->plu_base + MLXBF_GIGE_TX_FSM_POWERUP_CYCLES);
+
+	val = MLXBF_GIGE_TX_FSM_CAL_FLOW_VAL(const_factor);
+	writel(val, priv->plu_base + MLXBF_GIGE_TX_FSM_CAL_FLOW_CYCLES);
+
+	val = readl(priv->plu_base + MLXBF_GIGE_TX_FSM_CAL_ABORT_CYCLES);
+	val &= ~MLXBF_GIGE_TX_FSM_CAL_ABORT_MASK;
+	val |= FIELD_PREP(MLXBF_GIGE_TX_FSM_CAL_ABORT_MASK,
+			  MLXBF_GIGE_TX_FSM_CAL_ABORT_VAL(const_factor));
+	writel(val, priv->plu_base + MLXBF_GIGE_TX_FSM_CAL_ABORT_CYCLES);
+
+	/* rx_fsm_counters */
+	val = MLXBF_GIGE_RX_FSM_DEFAULT_VAL(const_factor);
+	writel(val, priv->plu_base + MLXBF_GIGE_RX_FSM_DEFAULT_CYCLES);
+
+	val = MLXBF_GIGE_RX_FSM_SLEEP_VAL(const_factor);
+	writel(val, priv->plu_base + MLXBF_GIGE_RX_FSM_SLEEP_CYCLES);
+
+	val = MLXBF_GIGE_RX_FSM_POWERUP_VAL(const_factor);
+	writel(val, priv->plu_base + MLXBF_GIGE_RX_FSM_POWERUP_CYCLES);
+
+	val = MLXBF_GIGE_RX_FSM_TERM_VAL(const_factor);
+	writel(val, priv->plu_base + MLXBF_GIGE_RX_FSM_TERM_CYCLES);
+
+	val = MLXBF_GIGE_RX_FSM_CAL_FLOW_VAL(const_factor);
+	writel(val, priv->plu_base + MLXBF_GIGE_RX_FSM_CAL_FLOW_CYCLES);
+
+	val = MLXBF_GIGE_RX_FSM_CAL_ABORT_VAL(const_factor);
+	writel(val, priv->plu_base + MLXBF_GIGE_RX_FSM_CAL_ABORT_CYCLES);
+
+	val = MLXBF_GIGE_RX_FSM_EQ_FLOW_VAL(const_factor);
+	writel(val, priv->plu_base + MLXBF_GIGE_RX_FSM_EQ_FLOW_CYCLES);
+
+	val = MLXBF_GIGE_RX_FSM_EQ_ABORT_VAL(const_factor);
+	writel(val, priv->plu_base + MLXBF_GIGE_RX_FSM_EQ_ABORT_CYCLES);
+
+	val = MLXBF_GIGE_RX_FSM_EOM_FLOW_VAL(const_factor);
+	writel(val, priv->plu_base + MLXBF_GIGE_RX_FSM_EOM_FLOW_CYCLES);
+
+	val = readl(priv->plu_base + MLXBF_GIGE_RX_FSM_CDR_LOCK_CYCLES);
+	val &= ~MLXBF_GIGE_RX_FSM_CDR_LOCK_MASK;
+	val |= FIELD_PREP(MLXBF_GIGE_RX_FSM_CDR_LOCK_MASK,
+			  MLXBF_GIGE_RX_FSM_CDR_LOCK_VAL(const_factor));
+	writel(val, priv->plu_base + MLXBF_GIGE_RX_FSM_CDR_LOCK_CYCLES);
+
+	/* periodic_flows_timer_max_value */
+	val = readl(priv->plu_base + MLXBF_GIGE_PERIOD_FLOWS_TIMER_MAX);
+	val &= ~MLXBF_GIGE_PERIOD_FLOWS_TIMER_MAX_MASK;
+	val |= FIELD_PREP(MLXBF_GIGE_PERIOD_FLOWS_TIMER_MAX_MASK,
+			  MLXBF_GIGE_PERIOD_FLOWS_TIMER_MAX_VAL(const_factor));
+	writel(val, priv->plu_base + MLXBF_GIGE_PERIOD_FLOWS_TIMER_MAX);
+
+	/* plltop.center.iddq_cycles */
+	val = readl(priv->plu_base + MLXBF_GIGE_PLL_IDDQ_CYCLES);
+	val &= ~MLXBF_GIGE_PLL_IDDQ_CYCLES_MASK;
+	val |= FIELD_PREP(MLXBF_GIGE_PLL_IDDQ_CYCLES_MASK,
+			  MLXBF_GIGE_PLL_IDDQ_CYCLES_VAL(const_factor));
+	writel(val, priv->plu_base + MLXBF_GIGE_PLL_IDDQ_CYCLES);
+
+	/* lanetop.center.iddq_cycles */
+	val = readl(priv->plu_base + MLXBF_GIGE_LANE_IDDQ_CYCLES);
+	val &= ~MLXBF_GIGE_LANE_IDDQ_CYCLES_MASK;
+	val |= FIELD_PREP(MLXBF_GIGE_LANE_IDDQ_CYCLES_MASK,
+			  MLXBF_GIGE_LANE_IDDQ_CYCLES_VAL(const_factor));
+	writel(val, priv->plu_base + MLXBF_GIGE_LANE_IDDQ_CYCLES);
+
+	/* lanetop.center.power_governor0 */
+	val = FIELD_PREP(MLXBF_GIGE_LANE_PWR_GOV0_RISE_MASK,
+			 MLXBF_GIGE_LANE_PWR_GOV0_RISE_VAL(const_factor));
+	val |= FIELD_PREP(MLXBF_GIGE_LANE_PWR_GOV0_FALL_MASK,
+			  MLXBF_GIGE_LANE_PWR_GOV0_FALL_VAL(const_factor));
+	writel(val, priv->plu_base + MLXBF_GIGE_LANE_PWR_GOV0);
+}
+
+static int mlxbf_gige_uphy_gw_write(struct mlxbf_gige *priv, u16 addr,
+				    u16 data, bool is_pll)
+{
+	u32 cmd, val;
+	int ret;
+
+	cmd = MLXBF_GIGE_UPHY_GW_CREATE_CMD(addr, data, 0, is_pll);
+
+	/* Send PLL or lane GW write request */
+	writel(cmd, priv->plu_base + MLXBF_GIGE_UPHY_GW(is_pll));
+
+	/* If the poll times out, drop the request */
+	ret = readl_poll_timeout_atomic(priv->plu_base +
+					MLXBF_GIGE_UPHY_GW(is_pll),
+					val,
+					!(val & MLXBF_GIGE_UPHY_GW_BUSY_MASK(is_pll)),
+					5, 1000000);
+	if (ret)
+		dev_dbg(priv->dev, "Failed to send GW write request\n");
+
+	return ret;
+}
+
+static int mlxbf_gige_uphy_gw_read(struct mlxbf_gige *priv, u16 addr,
+				   bool is_pll)
+{
+	u32 cmd, val;
+	int ret;
+
+	cmd = MLXBF_GIGE_UPHY_GW_CREATE_CMD(addr, 0, 1, is_pll);
+
+	/* Send PLL or lane GW read request */
+	writel(cmd, priv->plu_base + MLXBF_GIGE_UPHY_GW(is_pll));
+
+	/* If the poll times out, drop the request */
+	ret = readl_poll_timeout_atomic(priv->plu_base +
+					MLXBF_GIGE_UPHY_GW(is_pll),
+					val,
+					!(val & MLXBF_GIGE_UPHY_GW_BUSY_MASK(is_pll)),
+					5, 1000000);
+	if (ret) {
+		dev_dbg(priv->dev, "Failed to send GW read request\n");
+		return ret;
+	}
+
+	val = readl(priv->plu_base + MLXBF_GIGE_UPHY_GW_DESC0(is_pll));
+	val &= MLXBF_GIGE_UPHY_GW_DESC0_DATA_MASK(is_pll);
+
+	return val;
+}
+
+static int mlxbf_gige_load_uphy_clm_init_pkg(struct mlxbf_gige *priv)
+{
+	int ret = 0;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(mlxbf_gige_clm_init); i++) {
+		ret = mlxbf_gige_uphy_gw_write(priv,
+					       mlxbf_gige_clm_init[i].addr,
+					       mlxbf_gige_clm_init[i].wdata,
+					       true);
+		if (ret) {
+			dev_dbg(priv->dev, "Failed to load clm init pkg\n");
+			return ret;
+		}
+	}
+
+	return ret;
+}
+
+static int mlxbf_gige_load_clm_production_fuses(struct mlxbf_gige *priv)
+{
+	u8 bg_trim_room;
+	u8 cvb_trim_room;
+	u8 speedo_room;
+	int ret;
+	u32 val;
+
+	val = readl(priv->fuse_gw_io);
+	bg_trim_room = (val & MLXBF_GIGE_YU_BG_TRIM_ROOM_MASK) >>
+			MLXBF_GIGE_YU_BG_TRIM_ROOM_SHIFT;
+	cvb_trim_room = (val & MLXBF_GIGE_YU_CVB_TRIM_ROOM_MASK) >>
+			MLXBF_GIGE_YU_CVB_TRIM_ROOM_SHIFT;
+	speedo_room = (val & MLXBF_GIGE_YU_SPEEDO_ROOM_MASK) >>
+			MLXBF_GIGE_YU_SPEEDO_ROOM_SHIFT;
+
+	val = ((bg_trim_room >> MLXBF_GIGE_YU_FUSE_VALID_SHIFT) <<
+		MLXBF_GIGE_PLL_MGMT_BGAP_FUSE_CTRL_BG_TRIM_VLD_SHIFT);
+	val |= ((cvb_trim_room >> MLXBF_GIGE_YU_FUSE_VALID_SHIFT) <<
+		MLXBF_GIGE_PLL_MGMT_BGAP_FUSE_CTRL_CVB_TRIM_VLD_SHIFT);
+	val |= ((speedo_room >> MLXBF_GIGE_YU_FUSE_VALID_SHIFT) <<
+		MLXBF_GIGE_PLL_MGMT_BGAP_FUSE_CTRL_SPEEDO_VLD_SHIFT);
+	val |= ((bg_trim_room & MLXBF_GIGE_YU_FUSE_MASK) <<
+		MLXBF_GIGE_PLL_MGMT_BGAP_FUSE_CTRL_BG_TRIM_SHIFT);
+	val |= ((cvb_trim_room & MLXBF_GIGE_YU_FUSE_MASK) <<
+		MLXBF_GIGE_PLL_MGMT_BGAP_FUSE_CTRL_CVB_TRIM_SHIFT);
+	val |= ((speedo_room & MLXBF_GIGE_YU_FUSE_MASK) <<
+		MLXBF_GIGE_PLL_MGMT_BGAP_FUSE_CTRL_SPEEDO_SHIFT);
+
+	ret = mlxbf_gige_uphy_gw_write(priv, MLXBF_GIGE_MGMT_BGAP_FUSE_CTRL_ADDR, val, true);
+	if (ret)
+		dev_dbg(priv->dev, "Failed to load clm production fuses\n");
+
+	return ret;
+}
+
+static int mlxbf_gige_init_pll(struct mlxbf_gige *priv)
+{
+	int ret;
+
+	ret = mlxbf_gige_load_uphy_clm_init_pkg(priv);
+	if (ret)
+		return ret;
+
+	ret = mlxbf_gige_load_clm_production_fuses(priv);
+
+	return ret;
+}
+
+static int mlxbf_gige_lock_pll(struct mlxbf_gige *priv)
+{
+	int ret;
+	u32 val;
+
+	/* plltop.center.uphy_pll_rst_reg_ */
+	val = readl(priv->plu_base + MLXBF_GIGE_UPHY_PLL_RST_REG);
+	val |= MLXBF_GIGE_UPHY_PLL_RST_REG_MASK;
+	writel(val, priv->plu_base + MLXBF_GIGE_UPHY_PLL_RST_REG);
+
+	/* cause_or.clrcause.bulk */
+	val = readl(priv->plu_base + MLXBF_GIGE_PLL1X_CAUSE_CLRCAUSE_BULK);
+	val |= MLXBF_GIGE_PLL1X_CAUSE_CLRCAUSE_BULK_MASK;
+	writel(val, priv->plu_base + MLXBF_GIGE_PLL1X_CAUSE_CLRCAUSE_BULK);
+
+	writel(0, priv->plu_base + MLXBF_GIGE_PLL_CAL);
+
+	/* Stop polling when fsm state is UGL_PLL1X_FSM_STATE_SLEEP */
+	ret = readl_poll_timeout_atomic(priv->plu_base +
+					MLXBF_GIGE_PLL_FSM_CTRL,
+					val, (val == MLXBF_GIGE_UGL_PLL1X_FSM_STATE_SLEEP),
+					5, 1000000);
+	if (ret) {
+		dev_dbg(priv->dev, "Polling timeout on fsm state sleep\n");
+		return ret;
+	}
+
+	udelay(MLXBF_GIGE_PLL_STAB_TIME);
+
+	val = readl(priv->plu_base + MLXBF_GIGE_PLL_SLEEP_FW);
+	val |= MLXBF_GIGE_PLL_SLEEP_FW_MASK;
+	writel(val, priv->plu_base + MLXBF_GIGE_PLL_SLEEP_FW);
+
+	udelay(MLXBF_GIGE_PLL_STAB_TIME);
+	writel(MLXBF_GIGE_PLL_RCAL_MASK, priv->plu_base + MLXBF_GIGE_PLL_RCAL);
+
+	/* Stop polling when fsm state is UGL_PLL1X_FSM_STATE_IDLE */
+	ret = readl_poll_timeout_atomic(priv->plu_base +
+					MLXBF_GIGE_PLL_FSM_CTRL,
+					val, (val == MLXBF_GIGE_UGL_PLL1X_FSM_STATE_IDLE),
+					5, 1000000);
+	if (ret) {
+		dev_dbg(priv->dev, "Polling timeout on fsm state idle\n");
+		return ret;
+	}
+
+	val = readl(priv->plu_base + MLXBF_GIGE_PLL_SLEEP_FW);
+	val &= ~MLXBF_GIGE_PLL_SLEEP_FW_MASK;
+	writel(val, priv->plu_base + MLXBF_GIGE_PLL_SLEEP_FW);
+
+	writel(MLXBF_GIGE_PLL_CAL_MASK, priv->plu_base + MLXBF_GIGE_PLL_CAL);
+
+	/* Stop polling when cal_valid is different from 0 */
+	ret = readl_poll_timeout_atomic(priv->plu_base + MLXBF_GIGE_PLL_CAL_VLD,
+					val, !!(val & MLXBF_GIGE_PLL_CAL_VLD_MASK),
+					5, 1000000);
+	if (ret) {
+		dev_dbg(priv->dev, "Polling timeout on cal_valid\n");
+		return ret;
+	}
+
+	/* pll_enable */
+	val = readl(priv->plu_base + MLXBF_GIGE_PLL_ENABLE);
+	val |= MLXBF_GIGE_PLL_ENABLE_MASK;
+	writel(val, priv->plu_base + MLXBF_GIGE_PLL_ENABLE);
+
+	return ret;
+}
+
+static void mlxbf_gige_get_lane_out_of_rst(struct mlxbf_gige *priv)
+{
+	u32 val;
+
+	val = readl(priv->plu_base + MLXBF_GIGE_LANE_RST_REG);
+	val |= MLXBF_GIGE_LANE_RST_REG_MASK;
+	writel(val, priv->plu_base + MLXBF_GIGE_LANE_RST_REG);
+}
+
+static int mlxbf_gige_load_imem(struct mlxbf_gige *priv)
+{
+	u16 csum_status;
+	int ret = 0;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(mlxbf_gige_dlm_imem_init); i++) {
+		ret = mlxbf_gige_uphy_gw_write(priv,
+					       mlxbf_gige_dlm_imem_init[i].addr,
+					       mlxbf_gige_dlm_imem_init[i].wdata,
+					       false);
+		if (ret)
+			return ret;
+	}
+
+	/* Resets the internal counter for MLXBF_GIGE_DLM_IMEM_DATA_ADDR to base address */
+	ret = mlxbf_gige_uphy_gw_write(priv,
+				       mlxbf_gige_dlm_seq_imem_wr_en_init.addr,
+				       mlxbf_gige_dlm_seq_imem_wr_en_init.wdata,
+				       false);
+	if (ret)
+		return ret;
+
+	/* HW increments the address MLXBF_GIGE_DLM_IMEM_DATA_ADDR internally. */
+	for (i = 0; i < ARRAY_SIZE(mlxbf_gige_dlm_imem_data); i++) {
+		ret = mlxbf_gige_uphy_gw_write(priv,
+					       MLXBF_GIGE_LANE_IMEM_DATA_ADDR,
+					       mlxbf_gige_dlm_imem_data[i].wdata,
+					       false);
+		if (ret)
+			return ret;
+	}
+
+	ret = mlxbf_gige_uphy_gw_write(priv,
+				       mlxbf_gige_dlm_seq_imem_wr_dis_init.addr,
+				       mlxbf_gige_dlm_seq_imem_wr_dis_init.wdata,
+				       false);
+	if (ret)
+		return ret;
+
+	ret = mlxbf_gige_uphy_gw_write(priv,
+				       mlxbf_gige_dlm_seq_imem_csum_en.addr,
+				       mlxbf_gige_dlm_seq_imem_csum_en.wdata,
+				       false);
+	if (ret)
+		return ret;
+
+	udelay(MLXBF_GIGE_PLL_DLM_IMEM_CSUM_TIMEOUT);
+
+	ret = mlxbf_gige_uphy_gw_read(priv, MLXBF_GIGE_LANE_CSUM_STS_ADDR, false);
+	if (ret < 0)
+		return ret;
+
+	csum_status = ((ret & MLXBF_GIGE_IMEM_CSUM_STATUS_MASK) >>
+			MLXBF_GIGE_IMEM_CSUM_STATUS_SHIFT);
+
+	ret = mlxbf_gige_uphy_gw_write(priv,
+				       mlxbf_gige_dlm_seq_imem_csum_dis.addr,
+				       mlxbf_gige_dlm_seq_imem_csum_dis.wdata,
+				       false);
+	if (ret)
+		return ret;
+
+	if (csum_status != MLXBF_GIGE_IMEM_CSUM_RUN_AND_VALID) {
+		dev_err(priv->dev, "%s: invalid checksum\n", __func__);
+
+		/* recovery flow */
+		for (i = 0; i < ARRAY_SIZE(mlxbf_gige_dlm_seq_imem_bmap_clr); i++) {
+			mlxbf_gige_uphy_gw_write(priv,
+						 mlxbf_gige_dlm_seq_imem_bmap_clr[i].addr,
+						 mlxbf_gige_dlm_seq_imem_bmap_clr[i].wdata,
+						 false);
+		}
+
+		return MLXBF_GIGE_INVALID_IMEM_CSUM;
+	}
+
+	return ret;
+}
+
+static int mlxbf_gige_plu_tx_power_ctrl(struct mlxbf_gige *priv, bool is_pwr_on)
+{
+	int ret = 0;
+	u32 val;
+
+	val = readl(priv->plu_base + MLXBF_GIGE_LANE_TX_RATE_ID0_SPEED);
+	val &= ~MLXBF_GIGE_LANE_TX_SLEEP_VAL_MASK;
+	writel(val, priv->plu_base + MLXBF_GIGE_LANE_TX_RATE_ID0_SPEED);
+
+	if (is_pwr_on) {
+		val = readl(priv->plu_base + MLXBF_GIGE_LANE_TX_DATA_EN);
+		val &= ~MLXBF_GIGE_LANE_TX_IDDQ_VAL_MASK;
+		writel(val, priv->plu_base + MLXBF_GIGE_LANE_TX_DATA_EN);
+
+		val = readl(priv->plu_base + MLXBF_GIGE_PLU_POWERUP);
+		val |= MLXBF_GIGE_PLU_TX_POWERUP_MASK;
+		writel(val, priv->plu_base + MLXBF_GIGE_PLU_POWERUP);
+	} else {
+		val = readl(priv->plu_base + MLXBF_GIGE_PLU_POWERUP);
+		val &= ~MLXBF_GIGE_PLU_TX_POWERUP_MASK;
+		writel(val, priv->plu_base + MLXBF_GIGE_PLU_POWERUP);
+
+		val = readl(priv->plu_base + MLXBF_GIGE_LANE_TX_DATA_EN);
+		val |= MLXBF_GIGE_LANE_TX_IDDQ_VAL_MASK;
+		writel(val, priv->plu_base + MLXBF_GIGE_LANE_TX_DATA_EN);
+
+		ret = readl_poll_timeout_atomic(priv->plu_base +
+			MLXBF_GIGE_LANE_TX_FSM_CTRL, val,
+			((val & MLXBF_GIGE_LANE_TX_FSM_PS_MASK) == MLXBF_GIGE_TX_FSM_IDDQ),
+			5, 1000000);
+		if (ret)
+			dev_dbg(priv->dev, "Polling timeout on tx fsm iddq state\n");
+	}
+
+	return ret;
+}
+
+static int mlxbf_gige_dlm_tx_init_pkg(struct mlxbf_gige *priv)
+{
+	int ret = 0;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(mlxbf_gige_dlm_tx_init); i++) {
+		ret = mlxbf_gige_uphy_gw_write(priv,
+					       mlxbf_gige_dlm_tx_init[i].addr,
+					       mlxbf_gige_dlm_tx_init[i].wdata,
+					       false);
+		if (ret) {
+			dev_dbg(priv->dev, "Failed to load dlm tx init pkg\n");
+			return ret;
+		}
+	}
+
+	return ret;
+}
+
+static int mlxbf_gige_tx_lane_open(struct mlxbf_gige *priv)
+{
+	u32 val;
+	int ret;
+
+	/* Prepare the TX lane before opening it */
+
+	ret = mlxbf_gige_plu_tx_power_ctrl(priv, false);
+	if (ret)
+		return ret;
+
+	/* Calibration of TX elastic buffer */
+	val = readl(priv->plu_base + MLXBF_GIGE_LANE_TX_BITS_SWAP);
+	val &= ~MLXBF_GIGE_TX_EB_BLOCK_PUSH_DIST_MASK_MASK;
+	val |= MLXBF_GIGE_TX_EB_BLOCK_PUSH_DIST_MASK_VAL;
+	writel(val, priv->plu_base + MLXBF_GIGE_LANE_TX_BITS_SWAP);
+
+	val = readl(priv->plu_base + MLXBF_GIGE_LANE_TX_DATA_EN);
+	val |= MLXBF_GIGE_LANE_TX_DATA_EN_MASK;
+	writel(val, priv->plu_base + MLXBF_GIGE_LANE_TX_DATA_EN);
+
+	writel(MLXBF_GIGE_LANE_TX_CAL_MASK, priv->plu_base + MLXBF_GIGE_LANE_TX_CAL);
+
+	val = readl(priv->plu_base + MLXBF_GIGE_LANE_TX_DATA_EN);
+	val &= ~MLXBF_GIGE_LANE_TX_RATE_ID_MASK;
+	writel(val, priv->plu_base + MLXBF_GIGE_LANE_TX_DATA_EN);
+
+	val = readl(priv->plu_base + MLXBF_GIGE_LANE_TX_RATE_ID0_SPEED);
+	val &= ~MLXBF_GIGE_LANE_TX_RATE_ID0_SPEED_MASK;
+	writel(val, priv->plu_base + MLXBF_GIGE_LANE_TX_RATE_ID0_SPEED);
+
+	/* Loading the DLM tx init package should be done before lane power on */
+	ret = mlxbf_gige_dlm_tx_init_pkg(priv);
+	if (ret)
+		return ret;
+
+	val = readl(priv->plu_base + MLXBF_GIGE_LANE_TX_BITS_SWAP);
+	val &= ~MLXBF_GIGE_LANE_TX_BITS_SWAP_MASK;
+	writel(val, priv->plu_base + MLXBF_GIGE_LANE_TX_BITS_SWAP);
+
+	ret = mlxbf_gige_plu_tx_power_ctrl(priv, true);
+	if (ret)
+		return ret;
+
+	/* After preparing the TX lane, open it for data transmission */
+
+	val = readl(priv->plu_base + MLXBF_GIGE_LANE_TX_BITS_SWAP);
+	val &= ~MLXBF_GIGE_TX_EB_BLOCK_PUSH_DIST_MASK_MASK;
+	writel(val, priv->plu_base + MLXBF_GIGE_LANE_TX_BITS_SWAP);
+
+	ret = readl_poll_timeout_atomic(priv->plu_base +
+			MLXBF_GIGE_LANE_TX_FSM_CTRL, val,
+			((val & MLXBF_GIGE_LANE_TX_FSM_PS_MASK) == MLXBF_GIGE_TX_DATA_EN),
+			5, 1000000);
+	if (ret) {
+		dev_dbg(priv->dev, "Polling timeout on fsm tx data enable state\n");
+		return ret;
+	}
+
+	val = readl(priv->plu_base + MLXBF_GIGE_LANE_TX_DATA_EN);
+	val |= MLXBF_GIGE_LANE_TX_PERIODIC_CAL_EN_MASK;
+	writel(val, priv->plu_base + MLXBF_GIGE_LANE_TX_DATA_EN);
+
+	return ret;
+}
+
+static int mlxbf_gige_dlm_rx_init_pkg(struct mlxbf_gige *priv)
+{
+	int ret = 0;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(mlxbf_gige_dlm_rx_init); i++) {
+		ret = mlxbf_gige_uphy_gw_write(priv,
+					       mlxbf_gige_dlm_rx_init[i].addr,
+					       mlxbf_gige_dlm_rx_init[i].wdata,
+					       false);
+		if (ret) {
+			dev_dbg(priv->dev, "Failed to load dlm rx init pkg\n");
+			return ret;
+		}
+	}
+
+	return ret;
+}
+
+static int mlxbf_gige_plu_rx_power_ctrl(struct mlxbf_gige *priv, bool is_pwr_on)
+{
+	int ret = 0;
+	u32 val;
+
+	val = readl(priv->plu_base + MLXBF_GIGE_LANE_RX_RATE_ID);
+	val &= ~MLXBF_GIGE_LANE_RX_SLEEP_VAL_MASK;
+	writel(val, priv->plu_base + MLXBF_GIGE_LANE_RX_RATE_ID);
+
+	if (is_pwr_on) {
+		val = readl(priv->plu_base + MLXBF_GIGE_LANE_RX_RATE_ID);
+		val &= ~MLXBF_GIGE_LANE_RX_IDDQ_VAL_MASK;
+		writel(val, priv->plu_base + MLXBF_GIGE_LANE_RX_RATE_ID);
+
+		val = readl(priv->plu_base + MLXBF_GIGE_PLU_POWERUP);
+		val |= MLXBF_GIGE_PLU_RX_POWERUP_MASK;
+		writel(val, priv->plu_base + MLXBF_GIGE_PLU_POWERUP);
+	} else {
+		/* Enable HW watchdogs. */
+		val = readl(priv->plu_base + MLXBF_GIGE_LANE_RX_EQ_DONE_TIMER_EN);
+		val |= MLXBF_GIGE_LANE_RX_EQ_DONE_TIMER_EN_MASK;
+		val |= MLXBF_GIGE_LANE_RX_CAL_DONE_TIMER_EN_MASK;
+		writel(val, priv->plu_base + MLXBF_GIGE_LANE_RX_EQ_DONE_TIMER_EN);
+
+		val = readl(priv->plu_base + MLXBF_GIGE_PLU_POWERUP);
+		val &= ~MLXBF_GIGE_PLU_RX_POWERUP_MASK;
+		writel(val, priv->plu_base + MLXBF_GIGE_PLU_POWERUP);
+
+		val = readl(priv->plu_base + MLXBF_GIGE_LANE_RX_RATE_ID);
+		val |= MLXBF_GIGE_LANE_RX_IDDQ_VAL_MASK;
+		writel(val, priv->plu_base + MLXBF_GIGE_LANE_RX_RATE_ID);
+
+		ret = readl_poll_timeout_atomic(priv->plu_base +
+			MLXBF_GIGE_LANE_RX_FSM_CTRL, val,
+			((val & MLXBF_GIGE_LANE_RX_FSM_PS_MASK) == MLXBF_GIGE_RX_FSM_IDDQ),
+			5, 1000000);
+		if (ret) {
+			dev_dbg(priv->dev, "Polling timeout on rx fsm iddq state\n");
+			return ret;
+		}
+
+		val = readl(priv->plu_base + MLXBF_GIGE_LANE_RX_EQ_DONE_TIMER_EN);
+		val &= ~MLXBF_GIGE_LANE_RX_EQ_DONE_TIMER_EN_MASK;
+		val &= ~MLXBF_GIGE_LANE_RX_CAL_DONE_TIMER_EN_MASK;
+		writel(val, priv->plu_base + MLXBF_GIGE_LANE_RX_EQ_DONE_TIMER_EN);
+	}
+
+	return ret;
+}
+
+static int mlxbf_gige_rx_lane_open(struct mlxbf_gige *priv)
+{
+	u32 val;
+	int ret;
+
+	ret = mlxbf_gige_plu_rx_power_ctrl(priv, false);
+	if (ret)
+		return ret;
+
+	val = readl(priv->plu_base + MLXBF_GIGE_LANE_RX_RATE_ID);
+	val &= ~MLXBF_GIGE_LANE_RX_RATE_ID_MASK;
+	writel(val, priv->plu_base + MLXBF_GIGE_LANE_RX_RATE_ID);
+
+	val = readl(priv->plu_base + MLXBF_GIGE_LANE_RX_SYNC_FIFO_POP);
+	val &= ~MLXBF_GIGE_LANE_RX_SYNC_FIFO_POP_RDY_CHICKEN_MASK;
+	val &= ~MLXBF_GIGE_LANE_RX_DATA_SPLIT_LSB_VLD_CHICKEN_MASK;
+	writel(val, priv->plu_base + MLXBF_GIGE_LANE_RX_SYNC_FIFO_POP);
+
+	val = readl(priv->plu_base + MLXBF_GIGE_LANE_RX_RATE_ID);
+	val &= ~MLXBF_GIGE_LANE_RX_RATE_ID0_SPEED_MASK;
+	writel(val, priv->plu_base + MLXBF_GIGE_LANE_RX_RATE_ID);
+
+	ret = mlxbf_gige_dlm_rx_init_pkg(priv);
+	if (ret)
+		return ret;
+
+	writel(MLXBF_GIGE_LANE_RX_CAL_MASK, priv->plu_base + MLXBF_GIGE_LANE_RX_CAL);
+
+	val = readl(priv->plu_base + MLXBF_GIGE_LANE_RX_SYNC_FIFO_POP);
+	val &= ~MLXBF_GIGE_LANE_RX_CDR_RESET_REG_MASK;
+	val |= MLXBF_GIGE_LANE_RX_CDR_EN_MASK;
+	val |= MLXBF_GIGE_LANE_RX_DATA_EN_MASK;
+	writel(val, priv->plu_base + MLXBF_GIGE_LANE_RX_SYNC_FIFO_POP);
+
+	val = readl(priv->plu_base + MLXBF_GIGE_LANE_RX_EQ_TRAIN);
+	val &= ~MLXBF_GIGE_LANE_RX_EQ_TRAIN_MASK;
+	val |= MLXBF_GIGE_LANE_RX_EQ_TRAIN_VAL;
+	writel(val, priv->plu_base + MLXBF_GIGE_LANE_RX_EQ_TRAIN);
+
+	ret = mlxbf_gige_plu_rx_power_ctrl(priv, true);
+	if (ret)
+		return ret;
+
+	ret = readl_poll_timeout_atomic(priv->plu_base +
+			MLXBF_GIGE_LANE_RX_FSM_CTRL, val,
+			((val & MLXBF_GIGE_LANE_RX_FSM_PS_MASK) == MLXBF_GIGE_RX_FSM_ACTIVE),
+			5, 1000000);
+	if (ret)
+		dev_dbg(priv->dev, "Polling timeout on rx fsm active state\n");
+
+	return ret;
+}
+
+static bool mlxbf_gige_is_uphy_ready(struct mlxbf_gige *priv)
+{
+	u32 val;
+
+	val = readl(priv->plu_base + MLXBF_GIGE_LANE_TX_FSM_CTRL);
+	if ((val & MLXBF_GIGE_LANE_TX_FSM_PS_MASK) != MLXBF_GIGE_TX_DATA_EN)
+		return false;
+
+	val = readl(priv->plu_base + MLXBF_GIGE_LANE_RX_FSM_CTRL);
+	if ((val & MLXBF_GIGE_LANE_RX_FSM_PS_MASK) != MLXBF_GIGE_RX_FSM_ACTIVE)
+		return false;
+
+	return true;
+}
+
+int mlxbf_gige_config_uphy(struct mlxbf_gige *priv)
+{
+	struct platform_device *pdev = priv->pdev;
+	struct device *dev = &pdev->dev;
+	int ret = 0;
+
+	priv->fuse_gw_io = devm_platform_ioremap_resource(pdev, MLXBF_GIGE_RES_FUSE_GW);
+	if (IS_ERR(priv->fuse_gw_io))
+		return PTR_ERR(priv->fuse_gw_io);
+
+	if (mlxbf_gige_is_uphy_ready(priv))
+		return 0;
+
+	mlxbf_gige_ugl_static_config(priv);
+	ret = mlxbf_gige_init_pll(priv);
+	if (ret) {
+		dev_err(dev, "%s: Failed to initialize PLL\n", __func__);
+		return ret;
+	}
+
+	ret = mlxbf_gige_lock_pll(priv);
+	if (ret) {
+		dev_err(dev, "%s: Failed to lock PLL\n", __func__);
+		return ret;
+	}
+
+	/* Due to hardware design issue, we need to get the lanes out of reset
+	 * before configuring the imem.
+	 */
+	mlxbf_gige_get_lane_out_of_rst(priv);
+	ret = mlxbf_gige_load_imem(priv);
+	if (ret) {
+		dev_err(dev, "%s: Failed to load imem\n", __func__);
+		return ret;
+	}
+
+	ret = mlxbf_gige_tx_lane_open(priv);
+	if (ret) {
+		dev_err(dev, "%s: Failed to open tx lane\n", __func__);
+		return ret;
+	}
+
+	ret = mlxbf_gige_rx_lane_open(priv);
+	if (ret)
+		dev_err(dev, "%s: Failed to open rx lane\n", __func__);
+
+	return ret;
+}
diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_uphy.h b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_uphy.h
new file mode 100644
index 000000000000..914e627c302a
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_uphy.h
@@ -0,0 +1,398 @@ 
+/* SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause */
+
+/* UPHY support for Mellanox Gigabit Ethernet driver
+ *
+ * Copyright (C) 2022 NVIDIA CORPORATION & AFFILIATES
+ */
+
+#ifndef __MLXBF_GIGE_UPHY_H__
+#define __MLXBF_GIGE_UPHY_H__
+
+#include <linux/bitfield.h>
+
+/* Some registers' values depend on the p1clk clock. The following
+ * formula applies:
+ * ((time_in_ns*const_factor)/MLXBF_GIGE_TIME_FACTOR_TO_USEC)
+ */
+#define MLXBF_GIGE_TIME_FACTOR_TO_USEC          10000
+
+/* All addresses represent the offset from the base PLU address */
+
+#define MLXBF_GIGE_PLU_POWERUP                        0x488
+#define MLXBF_GIGE_PLU_TX_POWERUP_MASK                GENMASK(28, 28)
+#define MLXBF_GIGE_PLU_RX_POWERUP_MASK                GENMASK(27, 27)
+
+#define MLXBF_GIGE_LANE_CFG_FLAT0_BASE                0x23000
+#define MLXBF_GIGE_AE_SYS_IMEM_RAM_DATA_CTRL_WDATA    0x23ef8
+#define MLXBF_GIGE_AE_SYS_IMEM_RAM_STAT_IMEM_CSUM_STS 0x23f00
+#define MLXBF_GIGE_IMEM_CSUM_STATUS_MASK              GENMASK(6, 5)
+#define MLXBF_GIGE_IMEM_CSUM_STATUS_SHIFT             5
+
+#define MLXBF_GIGE_PLL_CFG_FLAT0_BASE                         0x25000
+#define MLXBF_GIGE_PLL_CFG_FLAT0_MGMT_BGAP_FUSE_CTRL          0x251d8
+#define MLXBF_GIGE_PLL_MGMT_BGAP_FUSE_CTRL_BG_TRIM_SHIFT      0
+#define MLXBF_GIGE_PLL_MGMT_BGAP_FUSE_CTRL_CVB_TRIM_SHIFT     4
+#define MLXBF_GIGE_PLL_MGMT_BGAP_FUSE_CTRL_SPEEDO_SHIFT       8
+#define MLXBF_GIGE_PLL_MGMT_BGAP_FUSE_CTRL_BG_TRIM_VLD_SHIFT  12
+#define MLXBF_GIGE_PLL_MGMT_BGAP_FUSE_CTRL_CVB_TRIM_VLD_SHIFT 13
+#define MLXBF_GIGE_PLL_MGMT_BGAP_FUSE_CTRL_SPEEDO_VLD_SHIFT   14
+
+#define MLXBF_GIGE_LANE_TX_FSM_CTRL                0x26000
+#define MLXBF_GIGE_LANE_TX_FSM_PS_MASK             GENMASK(3, 0)
+
+#define MLXBF_GIGE_LANE_TX_BITS_SWAP               0x2600c
+#define MLXBF_GIGE_TX_EB_BLOCK_PUSH_DIST_MASK_MASK GENMASK(20, 16)
+#define MLXBF_GIGE_TX_EB_BLOCK_PUSH_DIST_MASK_VAL  \
+	FIELD_PREP(MLXBF_GIGE_TX_EB_BLOCK_PUSH_DIST_MASK_MASK, 0x3)
+#define MLXBF_GIGE_LANE_TX_BITS_SWAP_MASK          GENMASK(0, 0)
+
+#define MLXBF_GIGE_LANE_TX_DATA_EN                 0x26010
+#define MLXBF_GIGE_LANE_TX_RATE_ID_MASK            GENMASK(30, 28)
+#define MLXBF_GIGE_LANE_TX_DATA_EN_MASK            GENMASK(23, 23)
+#define MLXBF_GIGE_LANE_TX_IDDQ_VAL_MASK           GENMASK(21, 21)
+#define MLXBF_GIGE_LANE_TX_PERIODIC_CAL_EN_MASK    GENMASK(17, 17)
+
+#define MLXBF_GIGE_LANE_TX_RATE_ID0_SPEED          0x26014
+#define MLXBF_GIGE_LANE_TX_SLEEP_VAL_MASK          GENMASK(9, 8)
+#define MLXBF_GIGE_LANE_TX_RATE_ID0_SPEED_MASK     GENMASK(2, 0)
+
+#define MLXBF_GIGE_LANE_TX_CAL                     0x26018
+#define MLXBF_GIGE_LANE_TX_CAL_MASK                GENMASK(0, 0)
+
+#define MLXBF_GIGE_LANE_RX_FSM_CTRL                0x26040
+#define MLXBF_GIGE_LANE_RX_FSM_PS_MASK             GENMASK(3, 0)
+
+#define MLXBF_GIGE_LANE_RX_EQ_DONE_TIMER_EN        0x26054
+#define MLXBF_GIGE_LANE_RX_EQ_DONE_TIMER_EN_MASK   GENMASK(31, 31)
+#define MLXBF_GIGE_LANE_RX_CAL_DONE_TIMER_EN_MASK  GENMASK(30, 30)
+
+#define MLXBF_GIGE_LANE_RX_RATE_ID                 0x26058
+#define MLXBF_GIGE_LANE_RX_RATE_ID0_SPEED_MASK     GENMASK(18, 16)
+#define MLXBF_GIGE_LANE_RX_RATE_ID_MASK            GENMASK(14, 12)
+#define MLXBF_GIGE_LANE_RX_SLEEP_VAL_MASK          GENMASK(7, 6)
+#define MLXBF_GIGE_LANE_RX_IDDQ_VAL_MASK           GENMASK(4, 4)
+
+#define MLXBF_GIGE_LANE_RX_CAL                     0x2605c
+#define MLXBF_GIGE_LANE_RX_CAL_MASK                GENMASK(0, 0)
+
+#define MLXBF_GIGE_LANE_RX_SYNC_FIFO_POP                   0x26060
+#define MLXBF_GIGE_LANE_RX_DATA_SPLIT_LSB_VLD_CHICKEN_MASK GENMASK(5, 5)
+#define MLXBF_GIGE_LANE_RX_SYNC_FIFO_POP_RDY_CHICKEN_MASK  GENMASK(4, 4)
+#define MLXBF_GIGE_LANE_RX_CDR_RESET_REG_MASK              GENMASK(3, 3)
+#define MLXBF_GIGE_LANE_RX_CDR_EN_MASK                     GENMASK(2, 2)
+#define MLXBF_GIGE_LANE_RX_DATA_EN_MASK                    GENMASK(1, 1)
+
+#define MLXBF_GIGE_LANE_RX_EQ_TRAIN        0x26064
+#define MLXBF_GIGE_LANE_RX_EQ_TRAIN_MASK   GENMASK(2, 0)
+#define MLXBF_GIGE_LANE_RX_EQ_TRAIN_VAL \
+	FIELD_PREP(MLXBF_GIGE_LANE_RX_EQ_TRAIN_MASK, 0x3)
+
+#define MLXBF_GIGE_LANE_GW                 0x26100
+#define MLXBF_GIGE_LANE_GW_ADDR_MASK       GENMASK(10, 1)
+#define MLXBF_GIGE_LANE_GW_RW_MASK         GENMASK(11, 11)
+#define MLXBF_GIGE_LANE_GW_DATA_MASK       GENMASK(27, 12)
+#define MLXBF_GIGE_LANE_GW_DATA_EN_MASK    GENMASK(28, 28)
+#define MLXBF_GIGE_LANE_GW_BUSY_MASK       GENMASK(30, 30)
+#define MLXBF_GIGE_LANE_GW_ADDR_SHIFT      1
+#define MLXBF_GIGE_LANE_GW_DESC0           0x2610c
+#define MLXBF_GIGE_LANE_GW_DESC0_DATA_MASK GENMASK(15, 0)
+
+#define MLXBF_GIGE_TX_FSM_DEFAULT_CYCLES     0x26600
+#define MLXBF_GIGE_TX_FSM_DEFAULT_VAL(const_factor) \
+	((200 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC)
+
+#define MLXBF_GIGE_TX_FSM_SLEEP_CYCLES       0x26604
+#define MLXBF_GIGE_TX_FSM_SLEEP_VAL(const_factor) \
+	((1000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC)
+
+#define MLXBF_GIGE_TX_FSM_POWERUP_CYCLES     0x26608
+#define MLXBF_GIGE_TX_FSM_POWERUP_VAL(const_factor) \
+	((10000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC)
+
+#define MLXBF_GIGE_TX_FSM_CAL_FLOW_CYCLES    0x2660c
+#define MLXBF_GIGE_TX_FSM_CAL_FLOW_VAL(const_factor) \
+	((200000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC)
+
+#define MLXBF_GIGE_TX_FSM_CAL_ABORT_CYCLES   0x26610
+#define MLXBF_GIGE_TX_FSM_CAL_ABORT_VAL(const_factor) \
+	((4000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC)
+#define MLXBF_GIGE_TX_FSM_CAL_ABORT_MASK     GENMASK(18, 0)
+
+#define MLXBF_GIGE_RX_FSM_DEFAULT_CYCLES     0x26614
+#define MLXBF_GIGE_RX_FSM_DEFAULT_VAL(const_factor) \
+	((200 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC)
+
+#define MLXBF_GIGE_RX_FSM_SLEEP_CYCLES       0x26618
+#define MLXBF_GIGE_RX_FSM_SLEEP_VAL(const_factor) \
+	((1000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC)
+
+#define MLXBF_GIGE_RX_FSM_POWERUP_CYCLES     0x2661c
+#define MLXBF_GIGE_RX_FSM_POWERUP_VAL(const_factor) \
+	((10000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC)
+
+#define MLXBF_GIGE_RX_FSM_TERM_CYCLES        0x26620
+#define MLXBF_GIGE_RX_FSM_TERM_VAL(const_factor) \
+	((200000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC)
+
+#define MLXBF_GIGE_RX_FSM_CAL_FLOW_CYCLES    0x26624
+#define MLXBF_GIGE_RX_FSM_CAL_FLOW_VAL(const_factor) \
+	((200000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC)
+
+#define MLXBF_GIGE_RX_FSM_CAL_ABORT_CYCLES   0x26628
+#define MLXBF_GIGE_RX_FSM_CAL_ABORT_VAL(const_factor) \
+	((4000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC)
+
+#define MLXBF_GIGE_RX_FSM_EQ_FLOW_CYCLES     0x2662c
+#define MLXBF_GIGE_RX_FSM_EQ_FLOW_VAL(const_factor) \
+	((48000000 / MLXBF_GIGE_TIME_FACTOR_TO_USEC) * (const_factor))
+
+#define MLXBF_GIGE_RX_FSM_EQ_ABORT_CYCLES    0x26630
+#define MLXBF_GIGE_RX_FSM_EQ_ABORT_VAL(const_factor) \
+	((4000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC)
+
+#define MLXBF_GIGE_RX_FSM_EOM_FLOW_CYCLES    0x26634
+#define MLXBF_GIGE_RX_FSM_EOM_FLOW_VAL(const_factor) \
+	((4000000 / MLXBF_GIGE_TIME_FACTOR_TO_USEC) * (const_factor))
+
+#define MLXBF_GIGE_RX_FSM_CDR_LOCK_CYCLES    0x26638
+#define MLXBF_GIGE_RX_FSM_CDR_LOCK_VAL(const_factor) \
+	((30000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC)
+#define MLXBF_GIGE_RX_FSM_CDR_LOCK_MASK      GENMASK(20, 0)
+
+#define MLXBF_GIGE_LANE_PWR_GOV0                   0x26650
+#define MLXBF_GIGE_LANE_PWR_GOV0_FALL_VAL(const_factor) \
+	((5000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC)
+#define MLXBF_GIGE_LANE_PWR_GOV0_FALL_MASK         GENMASK(31, 16)
+#define MLXBF_GIGE_LANE_PWR_GOV0_RISE_VAL(const_factor) \
+	((5000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC)
+#define MLXBF_GIGE_LANE_PWR_GOV0_RISE_MASK         GENMASK(15, 0)
+
+#define MLXBF_GIGE_LANE_IDDQ_CYCLES                0x26660
+#define MLXBF_GIGE_LANE_IDDQ_CYCLES_VAL(const_factor) \
+	((2000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC)
+#define MLXBF_GIGE_LANE_IDDQ_CYCLES_MASK           GENMASK(28, 16)
+
+#define MLXBF_GIGE_LANE_RST_REG                    0x26660
+#define MLXBF_GIGE_LANE_RST_REG_MASK               GENMASK(7, 6)
+
+#define MLXBF_GIGE_PERIOD_FLOWS_TIMER_MAX          0x26668
+#define MLXBF_GIGE_PERIOD_FLOWS_TIMER_MAX_VAL(const_factor) \
+	((2500000 / (MLXBF_GIGE_TIME_FACTOR_TO_USEC * 8)) * (const_factor))
+#define MLXBF_GIGE_PERIOD_FLOWS_TIMER_MAX_MASK     GENMASK(22, 0)
+
+#define MLXBF_GIGE_PLL_FSM_CTRL           0x26800
+#define MLXBF_GIGE_PLL_FSM_PS_MASK        GENMASK(3, 0)
+
+#define MLXBF_GIGE_PLL_GW                 0x26810
+#define MLXBF_GIGE_PLL_GW_ADDR_MASK       GENMASK(10, 1)
+#define MLXBF_GIGE_PLL_GW_RW_MASK         GENMASK(11, 11)
+#define MLXBF_GIGE_PLL_GW_DATA_MASK       GENMASK(27, 12)
+#define MLXBF_GIGE_PLL_GW_DATA_EN_MASK    GENMASK(28, 28)
+#define MLXBF_GIGE_PLL_GW_BUSY_MASK       GENMASK(30, 30)
+#define MLXBF_GIGE_PLL_GW_ADDR_SHIFT      1
+#define MLXBF_GIGE_PLL_GW_DESC0           0x2681c
+#define MLXBF_GIGE_PLL_GW_DESC0_DATA_MASK GENMASK(15, 0)
+
+#define MLXBF_GIGE_PLL_SLEEP_FW           0x26820
+#define MLXBF_GIGE_PLL_SLEEP_FW_MASK      GENMASK(14, 14)
+
+#define MLXBF_GIGE_PLL_ENABLE             0x26820
+#define MLXBF_GIGE_PLL_ENABLE_MASK        GENMASK(1, 1)
+
+#define MLXBF_GIGE_PLL_RCAL               0x26828
+#define MLXBF_GIGE_PLL_RCAL_MASK          GENMASK(0, 0)
+
+#define MLXBF_GIGE_PLL_CAL_VLD            0x2682c
+#define MLXBF_GIGE_PLL_CAL_VLD_MASK       GENMASK(1, 0)
+
+#define MLXBF_GIGE_PLL_CAL                0x26830
+#define MLXBF_GIGE_PLL_CAL_MASK           GENMASK(0, 0)
+
+#define MLXBF_GIGE_PLL1X_CAUSE_CLRCAUSE_BULK      0x26878
+#define MLXBF_GIGE_PLL1X_CAUSE_CLRCAUSE_BULK_MASK GENMASK(16, 0)
+
+#define MLXBF_GIGE_PLL1X_FSM_DEFAULT_CYCLES       0x26900
+#define MLXBF_GIGE_PLL1X_FSM_DEFAULT_VAL(const_factor) \
+	((250 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC)
+
+#define MLXBF_GIGE_PLL1X_FSM_SLEEP_CYCLES         0x26904
+#define MLXBF_GIGE_PLL1X_FSM_SLEEP_VAL(const_factor) \
+	((5000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC)
+
+#define MLXBF_GIGE_PLL1X_FSM_RCAL_FLOW_CYCLES     0x26908
+#define MLXBF_GIGE_PLL1X_FSM_RCAL_FLOW_VAL(const_factor) \
+	((40000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC)
+
+#define MLXBF_GIGE_PLL1X_FSM_CAL_FLOW_CYCLES      0x2690c
+#define MLXBF_GIGE_PLL1X_FSM_CAL_FLOW_VAL(const_factor) \
+	((300000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC)
+
+#define MLXBF_GIGE_PLL1X_FSM_LOCKDET_STS_CYCLES   0x26910
+#define MLXBF_GIGE_PLL1X_FSM_LOCKDET_STS_VAL(const_factor) \
+	((100000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC)
+#define MLXBF_GIGE_PLL1X_FSM_LOCKDET_STS_MASK     GENMASK(18, 0)
+
+#define MLXBF_GIGE_PLL_IDDQ_CYCLES           0x26914
+#define MLXBF_GIGE_PLL_IDDQ_CYCLES_VAL(const_factor) \
+	((2000 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC)
+#define MLXBF_GIGE_PLL_IDDQ_CYCLES_MASK      GENMASK(28, 16)
+
+#define MLXBF_GIGE_UPHY_PLL_RST_REG          0x26914
+#define MLXBF_GIGE_UPHY_PLL_RST_REG_MASK     GENMASK(2, 2)
+
+#define MLXBF_GIGE_UGL_CR_BRIDGE_DESC       0x26a90
+#define MLXBF_GIGE_UGL_CR_BRIDGE_SETUP_MASK GENMASK(5, 0)
+#define MLXBF_GIGE_UGL_CR_BRIDGE_PULSE_MASK GENMASK(13, 8)
+#define MLXBF_GIGE_UGL_CR_BRIDGE_HOLD_MASK  GENMASK(21, 16)
+#define MLXBF_GIGE_UGL_CR_BRIDGE_ALL_MASK \
+	(MLXBF_GIGE_UGL_CR_BRIDGE_SETUP_MASK | \
+	MLXBF_GIGE_UGL_CR_BRIDGE_PULSE_MASK | \
+	MLXBF_GIGE_UGL_CR_BRIDGE_HOLD_MASK)
+
+#define MLXBF_GIGE_UGL_CR_BRIDGE_SETUP_VAL(const_factor) \
+	((10 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC)
+#define MLXBF_GIGE_UGL_CR_BRIDGE_PULSE_VAL(const_factor) \
+	((30 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC)
+#define MLXBF_GIGE_UGL_CR_BRIDGE_HOLD_VAL(const_factor)  \
+	((10 * (const_factor)) / MLXBF_GIGE_TIME_FACTOR_TO_USEC)
+
+/* rw = 0 for write and 1 for read.
+ * data_en should be set to 1 only for a write transaction.
+ */
+#define MLXBF_GIGE_PLL_GW_CREATE_CMD(addr, data, rw) \
+	((((addr) << MLXBF_GIGE_PLL_GW_ADDR_SHIFT) & MLXBF_GIGE_PLL_GW_ADDR_MASK) | \
+	FIELD_PREP(MLXBF_GIGE_PLL_GW_DATA_MASK, data) | \
+	FIELD_PREP(MLXBF_GIGE_PLL_GW_BUSY_MASK, 1) | \
+	(rw ? FIELD_PREP(MLXBF_GIGE_PLL_GW_RW_MASK, 1) : \
+	 FIELD_PREP(MLXBF_GIGE_PLL_GW_DATA_EN_MASK, 1)))
+
+#define MLXBF_GIGE_LANE_GW_CREATE_CMD(addr, data, rw) \
+	((((addr) << MLXBF_GIGE_LANE_GW_ADDR_SHIFT) & MLXBF_GIGE_LANE_GW_ADDR_MASK) | \
+	FIELD_PREP(MLXBF_GIGE_LANE_GW_DATA_MASK, data) | \
+	FIELD_PREP(MLXBF_GIGE_LANE_GW_BUSY_MASK, 1) | \
+	(rw ? FIELD_PREP(MLXBF_GIGE_LANE_GW_RW_MASK, 1) : \
+	 FIELD_PREP(MLXBF_GIGE_LANE_GW_DATA_EN_MASK, 1)))
+
+#define MLXBF_GIGE_UPHY_GW_CREATE_CMD(addr, data, rw, is_pll) \
+	((is_pll) ? MLXBF_GIGE_PLL_GW_CREATE_CMD(addr, data, rw) : \
+	MLXBF_GIGE_LANE_GW_CREATE_CMD(addr, data, rw))
+
+#define MLXBF_GIGE_UPHY_GW(is_pll) \
+	((is_pll) ? MLXBF_GIGE_PLL_GW : MLXBF_GIGE_LANE_GW)
+
+#define MLXBF_GIGE_UPHY_GW_DESC0(is_pll) \
+	((is_pll) ? MLXBF_GIGE_PLL_GW_DESC0 : MLXBF_GIGE_LANE_GW_DESC0)
+
+#define MLXBF_GIGE_UPHY_GW_DESC0_DATA_MASK(is_pll) \
+	((is_pll) ? MLXBF_GIGE_PLL_GW_DESC0_DATA_MASK : \
+	MLXBF_GIGE_LANE_GW_DESC0_DATA_MASK)
+
+#define MLXBF_GIGE_UPHY_GW_BUSY_MASK(is_pll) \
+	((is_pll) ? MLXBF_GIGE_PLL_GW_BUSY_MASK : \
+	MLXBF_GIGE_LANE_GW_BUSY_MASK)
+
+/* bootrecord p1clk */
+#define MLXBF_GIGE_P1CLK_REG1        0x14
+#define MLXBF_GIGE_P1CLK_REG2        0x18
+#define MLXBF_GIGE_P1_CORE_F_SHIFT   0
+#define MLXBF_GIGE_P1_CORE_F_MASK    GENMASK(25, 0)
+#define MLXBF_GIGE_P1_CORE_R_SHIFT   26
+#define MLXBF_GIGE_P1_CORE_R_MASK    GENMASK(31, 26)
+#define MLXBF_GIGE_P1_CORE_OD_SHIFT  0
+#define MLXBF_GIGE_P1_CORE_OD_MASK   GENMASK(3, 0)
+
+#define MLXBF_GIGE_P1CLK_MULT_FACTOR 12
+#define MLXBF_GIGE_P1_FREQ_REFERENCE 156250000ULL
+#define MLXBF_GIGE_P1_CLK_CONST      16384ULL
+
+/* There is a 32-bit crspace to 16-bit UPHY address encoding.
+ * The 16-bit address can be accessed via the GW register.
+ * Subtract the crspace region base address from the actual
+ * address that needs to be accessed via the gw.
+ * Then divide it by 4 since crspace registers are 4 bit aligned
+ */
+#define MLXBF_GIGE_32B_TO_16B_ADDR(addr, base) (((addr) - (base)) >> 2)
+
+#define MLXBF_GIGE_LANE_CSUM_STS_ADDR \
+	MLXBF_GIGE_32B_TO_16B_ADDR( \
+	MLXBF_GIGE_AE_SYS_IMEM_RAM_STAT_IMEM_CSUM_STS, \
+	MLXBF_GIGE_LANE_CFG_FLAT0_BASE)
+
+#define MLXBF_GIGE_IMEM_CSUM_RUN_AND_VALID              0x3
+#define MLXBF_GIGE_INVALID_IMEM_CSUM                    -1
+
+#define MLXBF_GIGE_LANE_IMEM_DATA_ADDR \
+	MLXBF_GIGE_32B_TO_16B_ADDR( \
+	MLXBF_GIGE_AE_SYS_IMEM_RAM_DATA_CTRL_WDATA, \
+	MLXBF_GIGE_LANE_CFG_FLAT0_BASE)
+
+#define MLXBF_GIGE_MGMT_BGAP_FUSE_CTRL_ADDR \
+	MLXBF_GIGE_32B_TO_16B_ADDR( \
+	MLXBF_GIGE_PLL_CFG_FLAT0_MGMT_BGAP_FUSE_CTRL, \
+	MLXBF_GIGE_PLL_CFG_FLAT0_BASE)
+
+#define MLXBF_GIGE_YU_BG_TRIM_ROOM_MASK   GENMASK(4, 0)
+#define MLXBF_GIGE_YU_BG_TRIM_ROOM_SHIFT  0
+#define MLXBF_GIGE_YU_CVB_TRIM_ROOM_MASK  GENMASK(9, 5)
+#define MLXBF_GIGE_YU_CVB_TRIM_ROOM_SHIFT 5
+#define MLXBF_GIGE_YU_SPEEDO_ROOM_MASK    GENMASK(14, 10)
+#define MLXBF_GIGE_YU_SPEEDO_ROOM_SHIFT   10
+#define MLXBF_GIGE_YU_FUSE_VALID_SHIFT    4
+/* Fuse mask without valid bit */
+#define MLXBF_GIGE_YU_FUSE_MASK           0xf
+
+enum {
+	MLXBF_GIGE_UGL_PLL1X_FSM_STATE_IDDQ,
+	MLXBF_GIGE_UGL_PLL1X_FSM_STATE_SLEEP,
+	MLXBF_GIGE_UGL_PLL1X_FSM_STATE_RCAL_DONE_WAIT1,
+	MLXBF_GIGE_UGL_PLL1X_FSM_STATE_RCAL_DONE_WAIT0,
+	MLXBF_GIGE_UGL_PLL1X_FSM_STATE_IDLE,
+	MLXBF_GIGE_UGL_PLL1X_FSM_STATE_CAL_DONE_WAIT1,
+	MLXBF_GIGE_UGL_PLL1X_FSM_STATE_CAL_DONE_WAIT0,
+	MLXBF_GIGE_UGL_PLL1X_FSM_STATE_ACTIVE,
+	MLXBF_GIGE_UGL_PLL1X_FSM_STATE_LOCK,
+	MLXBF_GIGE_UGL_PLL1X_FSM_STATE_SPEED_CHANGE
+};
+
+enum {
+	MLXBF_GIGE_TX_FSM_IDDQ,
+	MLXBF_GIGE_TX_FSM_SLEEP,
+	MLXBF_GIGE_TX_FSM_SPEED_CHANGE,
+	MLXBF_GIGE_TX_FSM_POWERUP,
+	MLXBF_GIGE_TX_UGL_TX_POWERUP,
+	MLXBF_GIGE_TX_CAL_DONE_WAIT1,
+	MLXBF_GIGE_TX_CAL_ABORT,
+	MLXBF_GIGE_TX_CAL_ABORT_DONE_WAIT1,
+	MLXBF_GIGE_TX_CAL_DONE_WAIT0,
+	MLXBF_GIGE_TX_CAL_DONE,
+	MLXBF_GIGE_TX_DATA_READY,
+	MLXBF_GIGE_TX_DATA_EN_RDY,
+	MLXBF_GIGE_TX_DATA_EN
+};
+
+enum {
+	MLXBF_GIGE_RX_FSM_IDDQ,
+	MLXBF_GIGE_RX_FSM_SLEEP,
+	MLXBF_GIGE_RX_FSM_SPEED_CHANGE,
+	MLXBF_GIGE_RX_FSM_POWERUP,
+	MLXBF_GIGE_RX_FSM_CAL,
+	MLXBF_GIGE_RX_FSM_WAIT_TERM,
+	MLXBF_GIGE_RX_FSM_DATA_EN_RDY,
+	MLXBF_GIGE_RX_FSM_DATA_EN,
+	MLXBF_GIGE_RX_FSM_CDR_EN,
+	MLXBF_GIGE_RX_FSM_ACTIVE,
+	MLXBF_GIGE_RX_FSM_EQ,
+	MLXBF_GIGE_RX_FSM_EOM
+};
+
+#define MLXBF_GIGE_PLL_STAB_TIME             6 /* us */
+#define MLXBF_GIGE_PLL_DLM_IMEM_CSUM_TIMEOUT 15 /* us */
+
+struct mlxbf_gige_uphy_cfg_reg {
+	u16 addr;
+	u16 wdata;
+};
+
+int mlxbf_gige_config_uphy(struct mlxbf_gige *priv);
+
+#endif /* __MLXBF_GIGE_UPHY_H__ */