Commit 41fed17f authored by Vladimir Oltean's avatar Vladimir Oltean Committed by Jakub Kicinski

net: dsa: sja1105: add a translation table for port speeds

In order to support the new speed of 2500Mbps, the SJA1110 has achieved
the great performance of changing the encoding in the MAC Configuration
Table for the port speeds of 10, 100, 1000 compared to SJA1105.

Because this is a common driver, we need a layer of indirection in order
to program the hardware with the right values irrespective of switch
generation.
Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 91a05078
...@@ -72,6 +72,15 @@ struct sja1105_regs { ...@@ -72,6 +72,15 @@ struct sja1105_regs {
u64 stats[__MAX_SJA1105_STATS_AREA][SJA1105_MAX_NUM_PORTS]; u64 stats[__MAX_SJA1105_STATS_AREA][SJA1105_MAX_NUM_PORTS];
}; };
enum {
SJA1105_SPEED_AUTO,
SJA1105_SPEED_10MBPS,
SJA1105_SPEED_100MBPS,
SJA1105_SPEED_1000MBPS,
SJA1105_SPEED_2500MBPS,
SJA1105_SPEED_MAX,
};
struct sja1105_info { struct sja1105_info {
u64 device_id; u64 device_id;
/* Needed for distinction between P and R, and between Q and S /* Needed for distinction between P and R, and between Q and S
...@@ -116,6 +125,7 @@ struct sja1105_info { ...@@ -116,6 +125,7 @@ struct sja1105_info {
bool supports_rgmii[SJA1105_MAX_NUM_PORTS]; bool supports_rgmii[SJA1105_MAX_NUM_PORTS];
bool supports_sgmii[SJA1105_MAX_NUM_PORTS]; bool supports_sgmii[SJA1105_MAX_NUM_PORTS];
bool supports_2500basex[SJA1105_MAX_NUM_PORTS]; bool supports_2500basex[SJA1105_MAX_NUM_PORTS];
const u64 port_speed[SJA1105_SPEED_MAX];
}; };
enum sja1105_key_type { enum sja1105_key_type {
...@@ -314,13 +324,6 @@ typedef enum { ...@@ -314,13 +324,6 @@ typedef enum {
XMII_MODE_SGMII = 3, XMII_MODE_SGMII = 3,
} sja1105_phy_interface_t; } sja1105_phy_interface_t;
typedef enum {
SJA1105_SPEED_10MBPS = 3,
SJA1105_SPEED_100MBPS = 2,
SJA1105_SPEED_1000MBPS = 1,
SJA1105_SPEED_AUTO = 0,
} sja1105_speed_t;
int sja1105pqrs_setup_rgmii_delay(const void *ctx, int port); int sja1105pqrs_setup_rgmii_delay(const void *ctx, int port);
int sja1105_clocking_setup_port(struct sja1105_private *priv, int port); int sja1105_clocking_setup_port(struct sja1105_private *priv, int port);
int sja1105_clocking_setup(struct sja1105_private *priv); int sja1105_clocking_setup(struct sja1105_private *priv);
......
...@@ -328,7 +328,7 @@ sja1105_cgu_pll_control_packing(void *buf, struct sja1105_cgu_pll_ctrl *cmd, ...@@ -328,7 +328,7 @@ sja1105_cgu_pll_control_packing(void *buf, struct sja1105_cgu_pll_ctrl *cmd,
} }
static int sja1105_cgu_rgmii_tx_clk_config(struct sja1105_private *priv, static int sja1105_cgu_rgmii_tx_clk_config(struct sja1105_private *priv,
int port, sja1105_speed_t speed) int port, u64 speed)
{ {
const struct sja1105_regs *regs = priv->info->regs; const struct sja1105_regs *regs = priv->info->regs;
struct sja1105_cgu_mii_ctrl txc; struct sja1105_cgu_mii_ctrl txc;
...@@ -338,7 +338,7 @@ static int sja1105_cgu_rgmii_tx_clk_config(struct sja1105_private *priv, ...@@ -338,7 +338,7 @@ static int sja1105_cgu_rgmii_tx_clk_config(struct sja1105_private *priv,
if (regs->rgmii_tx_clk[port] == SJA1105_RSV_ADDR) if (regs->rgmii_tx_clk[port] == SJA1105_RSV_ADDR)
return 0; return 0;
if (speed == SJA1105_SPEED_1000MBPS) { if (speed == priv->info->port_speed[SJA1105_SPEED_1000MBPS]) {
clksrc = CLKSRC_PLL0; clksrc = CLKSRC_PLL0;
} else { } else {
int clk_sources[] = {CLKSRC_IDIV0, CLKSRC_IDIV1, CLKSRC_IDIV2, int clk_sources[] = {CLKSRC_IDIV0, CLKSRC_IDIV1, CLKSRC_IDIV2,
...@@ -524,35 +524,31 @@ static int sja1105_rgmii_clocking_setup(struct sja1105_private *priv, int port, ...@@ -524,35 +524,31 @@ static int sja1105_rgmii_clocking_setup(struct sja1105_private *priv, int port,
{ {
struct device *dev = priv->ds->dev; struct device *dev = priv->ds->dev;
struct sja1105_mac_config_entry *mac; struct sja1105_mac_config_entry *mac;
sja1105_speed_t speed; u64 speed;
int rc; int rc;
mac = priv->static_config.tables[BLK_IDX_MAC_CONFIG].entries; mac = priv->static_config.tables[BLK_IDX_MAC_CONFIG].entries;
speed = mac[port].speed; speed = mac[port].speed;
dev_dbg(dev, "Configuring port %d RGMII at speed %dMbps\n", dev_dbg(dev, "Configuring port %d RGMII at speed %lldMbps\n",
port, speed); port, speed);
switch (speed) { if (speed == priv->info->port_speed[SJA1105_SPEED_1000MBPS]) {
case SJA1105_SPEED_1000MBPS:
/* 1000Mbps, IDIV disabled (125 MHz) */ /* 1000Mbps, IDIV disabled (125 MHz) */
rc = sja1105_cgu_idiv_config(priv, port, false, 1); rc = sja1105_cgu_idiv_config(priv, port, false, 1);
break; } else if (speed == priv->info->port_speed[SJA1105_SPEED_100MBPS]) {
case SJA1105_SPEED_100MBPS:
/* 100Mbps, IDIV enabled, divide by 1 (25 MHz) */ /* 100Mbps, IDIV enabled, divide by 1 (25 MHz) */
rc = sja1105_cgu_idiv_config(priv, port, true, 1); rc = sja1105_cgu_idiv_config(priv, port, true, 1);
break; } else if (speed == priv->info->port_speed[SJA1105_SPEED_10MBPS]) {
case SJA1105_SPEED_10MBPS:
/* 10Mbps, IDIV enabled, divide by 10 (2.5 MHz) */ /* 10Mbps, IDIV enabled, divide by 10 (2.5 MHz) */
rc = sja1105_cgu_idiv_config(priv, port, true, 10); rc = sja1105_cgu_idiv_config(priv, port, true, 10);
break; } else if (speed == priv->info->port_speed[SJA1105_SPEED_AUTO]) {
case SJA1105_SPEED_AUTO:
/* Skip CGU configuration if there is no speed available /* Skip CGU configuration if there is no speed available
* (e.g. link is not established yet) * (e.g. link is not established yet)
*/ */
dev_dbg(dev, "Speed not available, skipping CGU config\n"); dev_dbg(dev, "Speed not available, skipping CGU config\n");
return 0; return 0;
default: } else {
rc = -EINVAL; rc = -EINVAL;
} }
......
...@@ -80,7 +80,7 @@ static int sja1105_init_mac_settings(struct sja1105_private *priv) ...@@ -80,7 +80,7 @@ static int sja1105_init_mac_settings(struct sja1105_private *priv)
/* Always put the MAC speed in automatic mode, where it can be /* Always put the MAC speed in automatic mode, where it can be
* adjusted at runtime by PHYLINK. * adjusted at runtime by PHYLINK.
*/ */
.speed = SJA1105_SPEED_AUTO, .speed = priv->info->port_speed[SJA1105_SPEED_AUTO],
/* No static correction for 1-step 1588 events */ /* No static correction for 1-step 1588 events */
.tp_delin = 0, .tp_delin = 0,
.tp_delout = 0, .tp_delout = 0,
...@@ -990,12 +990,19 @@ static void sja1105_sgmii_pcs_force_speed(struct sja1105_private *priv, ...@@ -990,12 +990,19 @@ static void sja1105_sgmii_pcs_force_speed(struct sja1105_private *priv,
} }
/* Convert link speed from SJA1105 to ethtool encoding */ /* Convert link speed from SJA1105 to ethtool encoding */
static int sja1105_speed[] = { static int sja1105_port_speed_to_ethtool(struct sja1105_private *priv,
[SJA1105_SPEED_AUTO] = SPEED_UNKNOWN, u64 speed)
[SJA1105_SPEED_10MBPS] = SPEED_10, {
[SJA1105_SPEED_100MBPS] = SPEED_100, if (speed == priv->info->port_speed[SJA1105_SPEED_10MBPS])
[SJA1105_SPEED_1000MBPS] = SPEED_1000, return SPEED_10;
}; if (speed == priv->info->port_speed[SJA1105_SPEED_100MBPS])
return SPEED_100;
if (speed == priv->info->port_speed[SJA1105_SPEED_1000MBPS])
return SPEED_1000;
if (speed == priv->info->port_speed[SJA1105_SPEED_2500MBPS])
return SPEED_2500;
return SPEED_UNKNOWN;
}
/* Set link speed in the MAC configuration for a specific port. */ /* Set link speed in the MAC configuration for a specific port. */
static int sja1105_adjust_port_config(struct sja1105_private *priv, int port, static int sja1105_adjust_port_config(struct sja1105_private *priv, int port,
...@@ -1003,7 +1010,7 @@ static int sja1105_adjust_port_config(struct sja1105_private *priv, int port, ...@@ -1003,7 +1010,7 @@ static int sja1105_adjust_port_config(struct sja1105_private *priv, int port,
{ {
struct sja1105_mac_config_entry *mac; struct sja1105_mac_config_entry *mac;
struct device *dev = priv->ds->dev; struct device *dev = priv->ds->dev;
sja1105_speed_t speed; u64 speed;
int rc; int rc;
/* On P/Q/R/S, one can read from the device via the MAC reconfiguration /* On P/Q/R/S, one can read from the device via the MAC reconfiguration
...@@ -1023,16 +1030,16 @@ static int sja1105_adjust_port_config(struct sja1105_private *priv, int port, ...@@ -1023,16 +1030,16 @@ static int sja1105_adjust_port_config(struct sja1105_private *priv, int port,
* ok for power consumption in case AN will never complete - * ok for power consumption in case AN will never complete -
* otherwise PHYLINK should come back with a new update. * otherwise PHYLINK should come back with a new update.
*/ */
speed = SJA1105_SPEED_AUTO; speed = priv->info->port_speed[SJA1105_SPEED_AUTO];
break; break;
case SPEED_10: case SPEED_10:
speed = SJA1105_SPEED_10MBPS; speed = priv->info->port_speed[SJA1105_SPEED_10MBPS];
break; break;
case SPEED_100: case SPEED_100:
speed = SJA1105_SPEED_100MBPS; speed = priv->info->port_speed[SJA1105_SPEED_100MBPS];
break; break;
case SPEED_1000: case SPEED_1000:
speed = SJA1105_SPEED_1000MBPS; speed = priv->info->port_speed[SJA1105_SPEED_1000MBPS];
break; break;
default: default:
dev_err(dev, "Invalid speed %iMbps\n", speed_mbps); dev_err(dev, "Invalid speed %iMbps\n", speed_mbps);
...@@ -1047,7 +1054,7 @@ static int sja1105_adjust_port_config(struct sja1105_private *priv, int port, ...@@ -1047,7 +1054,7 @@ static int sja1105_adjust_port_config(struct sja1105_private *priv, int port,
* we need to configure the PCS only (if even that). * we need to configure the PCS only (if even that).
*/ */
if (priv->phy_mode[port] == PHY_INTERFACE_MODE_SGMII) if (priv->phy_mode[port] == PHY_INTERFACE_MODE_SGMII)
mac[port].speed = SJA1105_SPEED_1000MBPS; mac[port].speed = priv->info->port_speed[SJA1105_SPEED_1000MBPS];
else else
mac[port].speed = speed; mac[port].speed = speed;
...@@ -1883,8 +1890,9 @@ int sja1105_static_config_reload(struct sja1105_private *priv, ...@@ -1883,8 +1890,9 @@ int sja1105_static_config_reload(struct sja1105_private *priv,
* change it through the dynamic interface later. * change it through the dynamic interface later.
*/ */
for (i = 0; i < ds->num_ports; i++) { for (i = 0; i < ds->num_ports; i++) {
speed_mbps[i] = sja1105_speed[mac[i].speed]; speed_mbps[i] = sja1105_port_speed_to_ethtool(priv,
mac[i].speed = SJA1105_SPEED_AUTO; mac[i].speed);
mac[i].speed = priv->info->port_speed[SJA1105_SPEED_AUTO];
if (priv->phy_mode[i] == PHY_INTERFACE_MODE_SGMII) if (priv->phy_mode[i] == PHY_INTERFACE_MODE_SGMII)
bmcr[i] = sja1105_sgmii_read(priv, i, bmcr[i] = sja1105_sgmii_read(priv, i,
......
...@@ -482,6 +482,13 @@ const struct sja1105_info sja1105e_info = { ...@@ -482,6 +482,13 @@ const struct sja1105_info sja1105e_info = {
.ptp_cmd_packing = sja1105et_ptp_cmd_packing, .ptp_cmd_packing = sja1105et_ptp_cmd_packing,
.clocking_setup = sja1105_clocking_setup, .clocking_setup = sja1105_clocking_setup,
.regs = &sja1105et_regs, .regs = &sja1105et_regs,
.port_speed = {
[SJA1105_SPEED_AUTO] = 0,
[SJA1105_SPEED_10MBPS] = 3,
[SJA1105_SPEED_100MBPS] = 2,
[SJA1105_SPEED_1000MBPS] = 1,
[SJA1105_SPEED_2500MBPS] = 0, /* Not supported */
},
.supports_mii = {true, true, true, true, true}, .supports_mii = {true, true, true, true, true},
.supports_rmii = {true, true, true, true, true}, .supports_rmii = {true, true, true, true, true},
.supports_rgmii = {true, true, true, true, true}, .supports_rgmii = {true, true, true, true, true},
...@@ -505,6 +512,13 @@ const struct sja1105_info sja1105t_info = { ...@@ -505,6 +512,13 @@ const struct sja1105_info sja1105t_info = {
.ptp_cmd_packing = sja1105et_ptp_cmd_packing, .ptp_cmd_packing = sja1105et_ptp_cmd_packing,
.clocking_setup = sja1105_clocking_setup, .clocking_setup = sja1105_clocking_setup,
.regs = &sja1105et_regs, .regs = &sja1105et_regs,
.port_speed = {
[SJA1105_SPEED_AUTO] = 0,
[SJA1105_SPEED_10MBPS] = 3,
[SJA1105_SPEED_100MBPS] = 2,
[SJA1105_SPEED_1000MBPS] = 1,
[SJA1105_SPEED_2500MBPS] = 0, /* Not supported */
},
.supports_mii = {true, true, true, true, true}, .supports_mii = {true, true, true, true, true},
.supports_rmii = {true, true, true, true, true}, .supports_rmii = {true, true, true, true, true},
.supports_rgmii = {true, true, true, true, true}, .supports_rgmii = {true, true, true, true, true},
...@@ -529,6 +543,13 @@ const struct sja1105_info sja1105p_info = { ...@@ -529,6 +543,13 @@ const struct sja1105_info sja1105p_info = {
.ptp_cmd_packing = sja1105pqrs_ptp_cmd_packing, .ptp_cmd_packing = sja1105pqrs_ptp_cmd_packing,
.clocking_setup = sja1105_clocking_setup, .clocking_setup = sja1105_clocking_setup,
.regs = &sja1105pqrs_regs, .regs = &sja1105pqrs_regs,
.port_speed = {
[SJA1105_SPEED_AUTO] = 0,
[SJA1105_SPEED_10MBPS] = 3,
[SJA1105_SPEED_100MBPS] = 2,
[SJA1105_SPEED_1000MBPS] = 1,
[SJA1105_SPEED_2500MBPS] = 0, /* Not supported */
},
.supports_mii = {true, true, true, true, true}, .supports_mii = {true, true, true, true, true},
.supports_rmii = {true, true, true, true, true}, .supports_rmii = {true, true, true, true, true},
.supports_rgmii = {true, true, true, true, true}, .supports_rgmii = {true, true, true, true, true},
...@@ -553,6 +574,13 @@ const struct sja1105_info sja1105q_info = { ...@@ -553,6 +574,13 @@ const struct sja1105_info sja1105q_info = {
.ptp_cmd_packing = sja1105pqrs_ptp_cmd_packing, .ptp_cmd_packing = sja1105pqrs_ptp_cmd_packing,
.clocking_setup = sja1105_clocking_setup, .clocking_setup = sja1105_clocking_setup,
.regs = &sja1105pqrs_regs, .regs = &sja1105pqrs_regs,
.port_speed = {
[SJA1105_SPEED_AUTO] = 0,
[SJA1105_SPEED_10MBPS] = 3,
[SJA1105_SPEED_100MBPS] = 2,
[SJA1105_SPEED_1000MBPS] = 1,
[SJA1105_SPEED_2500MBPS] = 0, /* Not supported */
},
.supports_mii = {true, true, true, true, true}, .supports_mii = {true, true, true, true, true},
.supports_rmii = {true, true, true, true, true}, .supports_rmii = {true, true, true, true, true},
.supports_rgmii = {true, true, true, true, true}, .supports_rgmii = {true, true, true, true, true},
...@@ -577,6 +605,13 @@ const struct sja1105_info sja1105r_info = { ...@@ -577,6 +605,13 @@ const struct sja1105_info sja1105r_info = {
.ptp_cmd_packing = sja1105pqrs_ptp_cmd_packing, .ptp_cmd_packing = sja1105pqrs_ptp_cmd_packing,
.clocking_setup = sja1105_clocking_setup, .clocking_setup = sja1105_clocking_setup,
.regs = &sja1105pqrs_regs, .regs = &sja1105pqrs_regs,
.port_speed = {
[SJA1105_SPEED_AUTO] = 0,
[SJA1105_SPEED_10MBPS] = 3,
[SJA1105_SPEED_100MBPS] = 2,
[SJA1105_SPEED_1000MBPS] = 1,
[SJA1105_SPEED_2500MBPS] = 0, /* Not supported */
},
.supports_mii = {true, true, true, true, true}, .supports_mii = {true, true, true, true, true},
.supports_rmii = {true, true, true, true, true}, .supports_rmii = {true, true, true, true, true},
.supports_rgmii = {true, true, true, true, true}, .supports_rgmii = {true, true, true, true, true},
...@@ -602,6 +637,13 @@ const struct sja1105_info sja1105s_info = { ...@@ -602,6 +637,13 @@ const struct sja1105_info sja1105s_info = {
.fdb_del_cmd = sja1105pqrs_fdb_del, .fdb_del_cmd = sja1105pqrs_fdb_del,
.ptp_cmd_packing = sja1105pqrs_ptp_cmd_packing, .ptp_cmd_packing = sja1105pqrs_ptp_cmd_packing,
.clocking_setup = sja1105_clocking_setup, .clocking_setup = sja1105_clocking_setup,
.port_speed = {
[SJA1105_SPEED_AUTO] = 0,
[SJA1105_SPEED_10MBPS] = 3,
[SJA1105_SPEED_100MBPS] = 2,
[SJA1105_SPEED_1000MBPS] = 1,
[SJA1105_SPEED_2500MBPS] = 0, /* Not supported */
},
.supports_mii = {true, true, true, true, true}, .supports_mii = {true, true, true, true, true},
.supports_rmii = {true, true, true, true, true}, .supports_rmii = {true, true, true, true, true},
.supports_rgmii = {true, true, true, true, true}, .supports_rgmii = {true, true, true, true, true},
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment