mirror of
https://git.openwrt.org/openwrt/openwrt.git
synced 2025-12-10 06:24:40 +01:00
Add a new microchipsw target aimed add supporting Microchip switch SoC-s. Start by supporting LAN969x SoC-s as the first subtarget. Signed-off-by: Robert Marko <robert.marko@sartura.hr>
175 lines
6.3 KiB
Diff
175 lines
6.3 KiB
Diff
From ec933122868bb205d8cdecc2049c49f811d32397 Mon Sep 17 00:00:00 2001
|
|
From: Daniel Machon <daniel.machon@microchip.com>
|
|
Date: Mon, 9 Sep 2024 17:14:49 +0200
|
|
Subject: [PATCH 15/25] 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: Daniel Machon <daniel.machon@microchip.com>
|
|
Reviewed-by: Steen Hegelund <Steen.Hegelund@microchip.com>
|
|
Link: https://lore.kernel.org/r/20240909-sparx5-lan969x-serdes-driver-v2-9-d695bcb57b84@microchip.com
|
|
Signed-off-by: Vinod Koul <vkoul@kernel.org>
|
|
---
|
|
drivers/phy/microchip/sparx5_serdes.c | 88 +++++++++++++++++++++++++++
|
|
drivers/phy/microchip/sparx5_serdes.h | 2 +
|
|
2 files changed, 90 insertions(+)
|
|
|
|
--- a/drivers/phy/microchip/sparx5_serdes.c
|
|
+++ b/drivers/phy/microchip/sparx5_serdes.c
|
|
@@ -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[T
|
|
[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 sp
|
|
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(st
|
|
{
|
|
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(struc
|
|
}
|
|
}
|
|
|
|
+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
|
|
{ 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_
|
|
},
|
|
};
|
|
|
|
+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 pl
|
|
|
|
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);
|
|
--- a/drivers/phy/microchip/sparx5_serdes.h
|
|
+++ b/drivers/phy/microchip/sparx5_serdes.h
|
|
@@ -36,6 +36,8 @@ enum sparx5_10g28cmu_mode {
|
|
|
|
enum sparx5_target {
|
|
SPX5_TARGET_SPARX5,
|
|
+ SPX5_TARGET_LAN969X,
|
|
+
|
|
};
|
|
|
|
struct sparx5_serdes_macro {
|