summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/dsa/sja1105/sja1105.h3
-rw-r--r--drivers/net/dsa/sja1105/sja1105_clocking.c5
-rw-r--r--drivers/net/dsa/sja1105/sja1105_main.c34
3 files changed, 41 insertions, 1 deletions
diff --git a/drivers/net/dsa/sja1105/sja1105.h b/drivers/net/dsa/sja1105/sja1105.h
index 50ab9282c4f1..87dee6794d98 100644
--- a/drivers/net/dsa/sja1105/sja1105.h
+++ b/drivers/net/dsa/sja1105/sja1105.h
@@ -48,11 +48,14 @@ struct sja1105_info {
const struct sja1105_table_ops *static_ops;
const struct sja1105_regs *regs;
int (*reset_cmd)(const void *ctx, const void *data);
+ int (*setup_rgmii_delay)(const void *ctx, int port);
const char *name;
};
struct sja1105_private {
struct sja1105_static_config static_config;
+ bool rgmii_rx_delay[SJA1105_NUM_PORTS];
+ bool rgmii_tx_delay[SJA1105_NUM_PORTS];
const struct sja1105_info *info;
struct gpio_desc *reset_gpio;
struct spi_device *spidev;
diff --git a/drivers/net/dsa/sja1105/sja1105_clocking.c b/drivers/net/dsa/sja1105/sja1105_clocking.c
index 598544297931..94bfe0ee50a8 100644
--- a/drivers/net/dsa/sja1105/sja1105_clocking.c
+++ b/drivers/net/dsa/sja1105/sja1105_clocking.c
@@ -427,7 +427,10 @@ static int sja1105_rgmii_clocking_setup(struct sja1105_private *priv, int port)
dev_err(dev, "Failed to configure Tx pad registers\n");
return rc;
}
- return 0;
+ if (!priv->info->setup_rgmii_delay)
+ return 0;
+
+ return priv->info->setup_rgmii_delay(priv, port);
}
static int sja1105_cgu_rmii_ref_clk_config(struct sja1105_private *priv,
diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c
index ec8137eff223..d27b9c178cba 100644
--- a/drivers/net/dsa/sja1105/sja1105_main.c
+++ b/drivers/net/dsa/sja1105/sja1105_main.c
@@ -518,6 +518,30 @@ static int sja1105_static_config_load(struct sja1105_private *priv,
return sja1105_static_config_upload(priv);
}
+static int sja1105_parse_rgmii_delays(struct sja1105_private *priv,
+ const struct sja1105_dt_port *ports)
+{
+ int i;
+
+ for (i = 0; i < SJA1105_NUM_PORTS; i++) {
+ if (ports->role == XMII_MAC)
+ continue;
+
+ if (ports->phy_mode == PHY_INTERFACE_MODE_RGMII_RXID ||
+ ports->phy_mode == PHY_INTERFACE_MODE_RGMII_ID)
+ priv->rgmii_rx_delay[i] = true;
+
+ if (ports->phy_mode == PHY_INTERFACE_MODE_RGMII_TXID ||
+ ports->phy_mode == PHY_INTERFACE_MODE_RGMII_ID)
+ priv->rgmii_tx_delay[i] = true;
+
+ if ((priv->rgmii_rx_delay[i] || priv->rgmii_tx_delay[i]) &&
+ !priv->info->setup_rgmii_delay)
+ return -EINVAL;
+ }
+ return 0;
+}
+
static int sja1105_parse_ports_node(struct sja1105_private *priv,
struct sja1105_dt_port *ports,
struct device_node *ports_node)
@@ -959,6 +983,16 @@ static int sja1105_setup(struct dsa_switch *ds)
dev_err(ds->dev, "Failed to parse DT: %d\n", rc);
return rc;
}
+
+ /* Error out early if internal delays are required through DT
+ * and we can't apply them.
+ */
+ rc = sja1105_parse_rgmii_delays(priv, ports);
+ if (rc < 0) {
+ dev_err(ds->dev, "RGMII delay not supported\n");
+ return rc;
+ }
+
/* Create and send configuration down to device */
rc = sja1105_static_config_load(priv, ports);
if (rc < 0) {