Commit c0a0a7ae authored by Daniel Machon's avatar Daniel Machon Committed by Vinod Koul
Browse files

phy: lan969x-serdes: add support for lan969x serdes driver



Add support for lan969x SERDES driver. Lan969x has ten 10G SERDES'es
which share the same features and data rates as the Sparx5 SERDES'es.

Signed-off-by: default avatarDaniel Machon <daniel.machon@microchip.com>
Reviewed-by: default avatarSteen Hegelund <Steen.Hegelund@microchip.com>
Link: https://lore.kernel.org/r/20240909-sparx5-lan969x-serdes-driver-v2-9-d695bcb57b84@microchip.com


Signed-off-by: default avatarVinod Koul <vkoul@kernel.org>
parent c5699055
Loading
Loading
Loading
Loading
+88 −0
Original line number Diff line number Diff line
@@ -25,6 +25,8 @@
#define SPX5_SERDES_25G_START 25
#define SPX5_SERDES_6G10G_CNT SPX5_SERDES_25G_START

#define LAN969X_SERDES_10G_CNT 10

/* Optimal power settings from GUC */
#define SPX5_SERDES_QUIET_MODE_VAL 0x01ef4e0c

@@ -36,6 +38,13 @@ const unsigned int sparx5_serdes_tsize[TSIZE_LAST] = {
	[TC_SD_LANE] = 25,
};

const unsigned int lan969x_serdes_tsize[TSIZE_LAST] = {
	[TC_SD10G_LANE] = 10,
	[TC_SD_CMU] = 6,
	[TC_SD_CMU_CFG] = 6,
	[TC_SD_LANE] = 10,
};

/* Pointer to the register target size table */
const unsigned int *tsize;

@@ -1096,6 +1105,24 @@ static int sparx5_serdes_cmu_get(enum sparx5_10g28cmu_mode mode, int sd_index)
	return sparx5_serdes_cmu_map[mode][sd_index];
}

/* Map of 6G/10G serdes mode and index to CMU index. */
static const int
lan969x_serdes_cmu_map[SPX5_SD10G28_CMU_MAX][LAN969X_SERDES_10G_CNT] = {
	[SPX5_SD10G28_CMU_MAIN] = { 2, 2, 2, 2, 2,
				    2, 2, 2, 5, 5 },
	[SPX5_SD10G28_CMU_AUX1] = { 0, 0, 3, 3, 3,
				    3, 3, 3, 3, 3 },
	[SPX5_SD10G28_CMU_AUX2] = { 1, 1, 1, 1, 4,
				    4, 4, 4, 4, 4 },
	[SPX5_SD10G28_CMU_NONE] = { 1, 1, 1, 1, 4,
				    4, 4, 4, 4, 4 },
};

static int lan969x_serdes_cmu_get(enum sparx5_10g28cmu_mode mode, int sd_index)
{
	return lan969x_serdes_cmu_map[mode][sd_index];
}

static void sparx5_serdes_cmu_power_off(struct sparx5_serdes_private *priv)
{
	void __iomem *cmu_inst, *cmu_cfg_inst;
@@ -2184,6 +2211,10 @@ static int sparx5_serdes_clock_config(struct sparx5_serdes_macro *macro)
{
	struct sparx5_serdes_private *priv = macro->priv;

	/* Clock is auto-detected in 100Base-FX mode on lan969x */
	if (priv->data->type == SPX5_TARGET_LAN969X)
		return 0;

	if (macro->serdesmode == SPX5_SD_MODE_100FX) {
		u32 freq = priv->coreclock == 250000000 ? 2 :
			priv->coreclock == 500000000 ? 1 : 0;
@@ -2395,6 +2426,12 @@ static void sparx5_serdes_type_set(struct sparx5_serdes_macro *macro, int sidx)
	}
}

static void lan969x_serdes_type_set(struct sparx5_serdes_macro *macro, int sidx)
{
	macro->serdestype = SPX5_SDT_10G;
	macro->stpidx = macro->sidx;
}

static int sparx5_phy_create(struct sparx5_serdes_private *priv,
			   int idx, struct phy **phy)
{
@@ -2519,6 +2556,41 @@ static struct sparx5_serdes_io_resource sparx5_serdes_iomap[] = {
	{ TARGET_SD_LANE_25G + 7, 0x5c8000 }, /* 0x610dd0000: sd_lane_25g_32 */
};

static const struct sparx5_serdes_io_resource lan969x_serdes_iomap[] =  {
	{ TARGET_SD_CMU,               0x0     }, /* 0xe3410000 */
	{ TARGET_SD_CMU +  1,          0x8000  }, /* 0xe3418000 */
	{ TARGET_SD_CMU +  2,          0x10000 }, /* 0xe3420000 */
	{ TARGET_SD_CMU +  3,          0x18000 }, /* 0xe3428000 */
	{ TARGET_SD_CMU +  4,          0x20000 }, /* 0xe3430000 */
	{ TARGET_SD_CMU +  5,          0x28000 }, /* 0xe3438000 */
	{ TARGET_SD_CMU_CFG,           0x30000 }, /* 0xe3440000 */
	{ TARGET_SD_CMU_CFG +  1,      0x38000 }, /* 0xe3448000 */
	{ TARGET_SD_CMU_CFG +  2,      0x40000 }, /* 0xe3450000 */
	{ TARGET_SD_CMU_CFG +  3,      0x48000 }, /* 0xe3458000 */
	{ TARGET_SD_CMU_CFG +  4,      0x50000 }, /* 0xe3460000 */
	{ TARGET_SD_CMU_CFG +  5,      0x58000 }, /* 0xe3468000 */
	{ TARGET_SD10G_LANE,           0x60000 }, /* 0xe3470000 */
	{ TARGET_SD10G_LANE +  1,      0x68000 }, /* 0xe3478000 */
	{ TARGET_SD10G_LANE +  2,      0x70000 }, /* 0xe3480000 */
	{ TARGET_SD10G_LANE +  3,      0x78000 }, /* 0xe3488000 */
	{ TARGET_SD10G_LANE +  4,      0x80000 }, /* 0xe3490000 */
	{ TARGET_SD10G_LANE +  5,      0x88000 }, /* 0xe3498000 */
	{ TARGET_SD10G_LANE +  6,      0x90000 }, /* 0xe34a0000 */
	{ TARGET_SD10G_LANE +  7,      0x98000 }, /* 0xe34a8000 */
	{ TARGET_SD10G_LANE +  8,      0xa0000 }, /* 0xe34b0000 */
	{ TARGET_SD10G_LANE +  9,      0xa8000 }, /* 0xe34b8000 */
	{ TARGET_SD_LANE,             0x100000 }, /* 0xe3510000 */
	{ TARGET_SD_LANE +  1,        0x108000 }, /* 0xe3518000 */
	{ TARGET_SD_LANE +  2,        0x110000 }, /* 0xe3520000 */
	{ TARGET_SD_LANE +  3,        0x118000 }, /* 0xe3528000 */
	{ TARGET_SD_LANE +  4,        0x120000 }, /* 0xe3530000 */
	{ TARGET_SD_LANE +  5,        0x128000 }, /* 0xe3538000 */
	{ TARGET_SD_LANE +  6,        0x130000 }, /* 0xe3540000 */
	{ TARGET_SD_LANE +  7,        0x138000 }, /* 0xe3548000 */
	{ TARGET_SD_LANE +  8,        0x140000 }, /* 0xe3550000 */
	{ TARGET_SD_LANE +  9,        0x148000 }, /* 0xe3558000 */
};

static const struct sparx5_serdes_match_data sparx5_desc = {
	.type = SPX5_TARGET_SPARX5,
	.iomap = sparx5_serdes_iomap,
@@ -2534,6 +2606,21 @@ static const struct sparx5_serdes_match_data sparx5_desc = {
	},
};

static const struct sparx5_serdes_match_data lan969x_desc = {
	.type = SPX5_TARGET_LAN969X,
	.iomap = lan969x_serdes_iomap,
	.iomap_size = ARRAY_SIZE(lan969x_serdes_iomap),
	.tsize = lan969x_serdes_tsize,
	.consts = {
		.sd_max       = 10,
		.cmu_max      = 6,
	},
	.ops = {
		.serdes_type_set      = &lan969x_serdes_type_set,
		.serdes_cmu_get       = &lan969x_serdes_cmu_get,
	}
};

/* Client lookup function, uses serdes index */
static struct phy *sparx5_serdes_xlate(struct device *dev,
				     const struct of_phandle_args *args)
@@ -2635,6 +2722,7 @@ static int sparx5_serdes_probe(struct platform_device *pdev)

static const struct of_device_id sparx5_serdes_match[] = {
	{ .compatible = "microchip,sparx5-serdes", .data = &sparx5_desc },
	{ .compatible = "microchip,lan9691-serdes", .data = &lan969x_desc },
	{ }
};
MODULE_DEVICE_TABLE(of, sparx5_serdes_match);
+2 −0
Original line number Diff line number Diff line
@@ -36,6 +36,8 @@ enum sparx5_10g28cmu_mode {

enum sparx5_target {
	SPX5_TARGET_SPARX5,
	SPX5_TARGET_LAN969X,

};

struct sparx5_serdes_macro {