@@ -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
@@ -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() */
@@ -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;
@@ -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);
new file mode 100644
@@ -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;
+}
new file mode 100644
@@ -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__ */