Commit 3e77e59b authored by Vladimir Oltean's avatar Vladimir Oltean Committed by David S. Miller

net: dsa: sja1105: add support for the SJA1110 switch family

The SJA1110 is basically an SJA1105 with more ports, some integrated
PHYs (100base-T1 and 100base-TX) and an embedded microcontroller which
can be disabled, and the switch core can be controlled by a host running
Linux, over SPI.

This patch contains:
- the static and dynamic config packing functions, for the tables that
  are common with SJA1105
- one more static config tables which is "unique" to the SJA1110
  (actually it is a rehash of stuff that was placed somewhere else in
  SJA1105): the PCP Remapping Table
- a reset and clock configuration procedure for the SJA1110 switch.
  This resets just the switch subsystem, and gates off the clock which
  powers on the embedded microcontroller.
- an RGMII delay configuration procedure for SJA1110, which is very
  similar to SJA1105, but different enough for us to be unable to reuse
  it (this is a pattern that repeats itself)
- some adaptations to dynamic config table entries which are no longer
  programmed in the same way. For example, to delete a VLAN, you used to
  write an entry through the dynamic reconfiguration interface with the
  desired VLAN ID, and with the VALIDENT bit set to false. Now, the VLAN
  table entries contain a TYPE_ENTRY field, which must be set to zero
  (in a backwards-incompatible way) in order for the entry to be deleted,
  or to some other entry for the VLAN to match "inner tagged" or "outer
  tagged" packets.
- a similar thing for the static config: the xMII Mode Parameters Table
  encoding for SGMII and MII (the latter just when attached to a
  100base-TX PHY) just isn't what it used to be in SJA1105. They are
  identical, except there is an extra "special" bit which needs to be
  set. Set it.
Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 070f5b70
...@@ -13,15 +13,12 @@ ...@@ -13,15 +13,12 @@
#include <linux/mutex.h> #include <linux/mutex.h>
#include "sja1105_static_config.h" #include "sja1105_static_config.h"
#define SJA1105_NUM_PORTS 5
#define SJA1105_MAX_NUM_PORTS SJA1105_NUM_PORTS
#define SJA1105_NUM_TC 8
#define SJA1105ET_FDB_BIN_SIZE 4 #define SJA1105ET_FDB_BIN_SIZE 4
/* The hardware value is in multiples of 10 ms. /* The hardware value is in multiples of 10 ms.
* The passed parameter is in multiples of 1 ms. * The passed parameter is in multiples of 1 ms.
*/ */
#define SJA1105_AGEING_TIME_MS(ms) ((ms) / 10) #define SJA1105_AGEING_TIME_MS(ms) ((ms) / 10)
#define SJA1105_NUM_L2_POLICERS 45 #define SJA1105_NUM_L2_POLICERS SJA1110_MAX_L2_POLICING_COUNT
typedef enum { typedef enum {
SPI_READ = 0, SPI_READ = 0,
...@@ -99,6 +96,7 @@ struct sja1105_info { ...@@ -99,6 +96,7 @@ struct sja1105_info {
int ptpegr_ts_bytes; int ptpegr_ts_bytes;
int num_cbs_shapers; int num_cbs_shapers;
int max_frame_mem; int max_frame_mem;
int num_ports;
const struct sja1105_dynamic_table_ops *dyn_ops; const struct sja1105_dynamic_table_ops *dyn_ops;
const struct sja1105_table_ops *static_ops; const struct sja1105_table_ops *static_ops;
const struct sja1105_regs *regs; const struct sja1105_regs *regs;
...@@ -310,6 +308,10 @@ extern const struct sja1105_info sja1105p_info; ...@@ -310,6 +308,10 @@ extern const struct sja1105_info sja1105p_info;
extern const struct sja1105_info sja1105q_info; extern const struct sja1105_info sja1105q_info;
extern const struct sja1105_info sja1105r_info; extern const struct sja1105_info sja1105r_info;
extern const struct sja1105_info sja1105s_info; extern const struct sja1105_info sja1105s_info;
extern const struct sja1105_info sja1110a_info;
extern const struct sja1105_info sja1110b_info;
extern const struct sja1105_info sja1110c_info;
extern const struct sja1105_info sja1110d_info;
/* From sja1105_clocking.c */ /* From sja1105_clocking.c */
...@@ -326,8 +328,10 @@ typedef enum { ...@@ -326,8 +328,10 @@ typedef enum {
} sja1105_phy_interface_t; } sja1105_phy_interface_t;
int sja1105pqrs_setup_rgmii_delay(const void *ctx, int port); int sja1105pqrs_setup_rgmii_delay(const void *ctx, int port);
int sja1110_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);
int sja1110_clocking_setup(struct sja1105_private *priv);
/* From sja1105_ethtool.c */ /* From sja1105_ethtool.c */
void sja1105_get_ethtool_stats(struct dsa_switch *ds, int port, u64 *data); void sja1105_get_ethtool_stats(struct dsa_switch *ds, int port, u64 *data);
...@@ -348,6 +352,18 @@ enum sja1105_iotag { ...@@ -348,6 +352,18 @@ enum sja1105_iotag {
SJA1105_S_TAG = 1, /* Outer VLAN header */ SJA1105_S_TAG = 1, /* Outer VLAN header */
}; };
enum sja1110_vlan_type {
SJA1110_VLAN_INVALID = 0,
SJA1110_VLAN_C_TAG = 1, /* Single inner VLAN tag */
SJA1110_VLAN_S_TAG = 2, /* Single outer VLAN tag */
SJA1110_VLAN_D_TAG = 3, /* Double tagged, use outer tag for lookup */
};
enum sja1110_shaper_type {
SJA1110_LEAKY_BUCKET_SHAPER = 0,
SJA1110_CBS_SHAPER = 1,
};
u8 sja1105et_fdb_hash(struct sja1105_private *priv, const u8 *addr, u16 vid); u8 sja1105et_fdb_hash(struct sja1105_private *priv, const u8 *addr, u16 vid);
int sja1105et_fdb_add(struct dsa_switch *ds, int port, int sja1105et_fdb_add(struct dsa_switch *ds, int port,
const unsigned char *addr, u16 vid); const unsigned char *addr, u16 vid);
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include "sja1105.h" #include "sja1105.h"
#define SJA1105_SIZE_CGU_CMD 4 #define SJA1105_SIZE_CGU_CMD 4
#define SJA1110_BASE_TIMER_CLK SJA1110_CGU_ADDR(0x74)
/* Common structure for CFG_PAD_MIIx_RX and CFG_PAD_MIIx_TX */ /* Common structure for CFG_PAD_MIIx_RX and CFG_PAD_MIIx_TX */
struct sja1105_cfg_pad_mii { struct sja1105_cfg_pad_mii {
...@@ -61,6 +62,12 @@ struct sja1105_cgu_pll_ctrl { ...@@ -61,6 +62,12 @@ struct sja1105_cgu_pll_ctrl {
u64 pd; u64 pd;
}; };
struct sja1110_cgu_outclk {
u64 clksrc;
u64 autoblock;
u64 pd;
};
enum { enum {
CLKSRC_MII0_TX_CLK = 0x00, CLKSRC_MII0_TX_CLK = 0x00,
CLKSRC_MII0_RX_CLK = 0x01, CLKSRC_MII0_RX_CLK = 0x01,
...@@ -461,6 +468,35 @@ sja1105_cfg_pad_mii_id_packing(void *buf, struct sja1105_cfg_pad_mii_id *cmd, ...@@ -461,6 +468,35 @@ sja1105_cfg_pad_mii_id_packing(void *buf, struct sja1105_cfg_pad_mii_id *cmd,
sja1105_packing(buf, &cmd->txc_pd, 0, 0, size, op); sja1105_packing(buf, &cmd->txc_pd, 0, 0, size, op);
} }
static void
sja1110_cfg_pad_mii_id_packing(void *buf, struct sja1105_cfg_pad_mii_id *cmd,
enum packing_op op)
{
const int size = SJA1105_SIZE_CGU_CMD;
u64 range = 4;
/* Fields RXC_RANGE and TXC_RANGE select the input frequency range:
* 0 = 2.5MHz
* 1 = 25MHz
* 2 = 50MHz
* 3 = 125MHz
* 4 = Automatically determined by port speed.
* There's no point in defining a structure different than the one for
* SJA1105, so just hardcode the frequency range to automatic, just as
* before.
*/
sja1105_packing(buf, &cmd->rxc_stable_ovr, 26, 26, size, op);
sja1105_packing(buf, &cmd->rxc_delay, 25, 21, size, op);
sja1105_packing(buf, &range, 20, 18, size, op);
sja1105_packing(buf, &cmd->rxc_bypass, 17, 17, size, op);
sja1105_packing(buf, &cmd->rxc_pd, 16, 16, size, op);
sja1105_packing(buf, &cmd->txc_stable_ovr, 10, 10, size, op);
sja1105_packing(buf, &cmd->txc_delay, 9, 5, size, op);
sja1105_packing(buf, &range, 4, 2, size, op);
sja1105_packing(buf, &cmd->txc_bypass, 1, 1, size, op);
sja1105_packing(buf, &cmd->txc_pd, 0, 0, size, op);
}
/* Valid range in degrees is an integer between 73.8 and 101.7 */ /* Valid range in degrees is an integer between 73.8 and 101.7 */
static u64 sja1105_rgmii_delay(u64 phase) static u64 sja1105_rgmii_delay(u64 phase)
{ {
...@@ -519,6 +555,35 @@ int sja1105pqrs_setup_rgmii_delay(const void *ctx, int port) ...@@ -519,6 +555,35 @@ int sja1105pqrs_setup_rgmii_delay(const void *ctx, int port)
packed_buf, SJA1105_SIZE_CGU_CMD); packed_buf, SJA1105_SIZE_CGU_CMD);
} }
int sja1110_setup_rgmii_delay(const void *ctx, int port)
{
const struct sja1105_private *priv = ctx;
const struct sja1105_regs *regs = priv->info->regs;
struct sja1105_cfg_pad_mii_id pad_mii_id = {0};
u8 packed_buf[SJA1105_SIZE_CGU_CMD] = {0};
pad_mii_id.rxc_pd = 1;
pad_mii_id.txc_pd = 1;
if (priv->rgmii_rx_delay[port]) {
pad_mii_id.rxc_delay = sja1105_rgmii_delay(90);
/* The "BYPASS" bit in SJA1110 is actually a "don't bypass" */
pad_mii_id.rxc_bypass = 1;
pad_mii_id.rxc_pd = 0;
}
if (priv->rgmii_tx_delay[port]) {
pad_mii_id.txc_delay = sja1105_rgmii_delay(90);
pad_mii_id.txc_bypass = 1;
pad_mii_id.txc_pd = 0;
}
sja1110_cfg_pad_mii_id_packing(packed_buf, &pad_mii_id, PACK);
return sja1105_xfer_buf(priv, SPI_WRITE, regs->pad_mii_id[port],
packed_buf, SJA1105_SIZE_CGU_CMD);
}
static int sja1105_rgmii_clocking_setup(struct sja1105_private *priv, int port, static int sja1105_rgmii_clocking_setup(struct sja1105_private *priv, int port,
sja1105_mii_role_t role) sja1105_mii_role_t role)
{ {
...@@ -755,3 +820,29 @@ int sja1105_clocking_setup(struct sja1105_private *priv) ...@@ -755,3 +820,29 @@ int sja1105_clocking_setup(struct sja1105_private *priv)
} }
return 0; return 0;
} }
static void
sja1110_cgu_outclk_packing(void *buf, struct sja1110_cgu_outclk *outclk,
enum packing_op op)
{
const int size = 4;
sja1105_packing(buf, &outclk->clksrc, 27, 24, size, op);
sja1105_packing(buf, &outclk->autoblock, 11, 11, size, op);
sja1105_packing(buf, &outclk->pd, 0, 0, size, op);
}
/* Power down the BASE_TIMER_CLK in order to disable the watchdog */
int sja1110_clocking_setup(struct sja1105_private *priv)
{
u8 packed_buf[SJA1105_SIZE_CGU_CMD] = {0};
struct sja1110_cgu_outclk outclk_7_c = {
.clksrc = 0x5,
.pd = true,
};
sja1110_cgu_outclk_packing(packed_buf, &outclk_7_c, PACK);
return sja1105_xfer_buf(priv, SPI_WRITE, SJA1110_BASE_TIMER_CLK,
packed_buf, SJA1105_SIZE_CGU_CMD);
}
...@@ -36,5 +36,6 @@ struct sja1105_mgmt_entry { ...@@ -36,5 +36,6 @@ struct sja1105_mgmt_entry {
extern const struct sja1105_dynamic_table_ops sja1105et_dyn_ops[BLK_IDX_MAX_DYN]; extern const struct sja1105_dynamic_table_ops sja1105et_dyn_ops[BLK_IDX_MAX_DYN];
extern const struct sja1105_dynamic_table_ops sja1105pqrs_dyn_ops[BLK_IDX_MAX_DYN]; extern const struct sja1105_dynamic_table_ops sja1105pqrs_dyn_ops[BLK_IDX_MAX_DYN];
extern const struct sja1105_dynamic_table_ops sja1110_dyn_ops[BLK_IDX_MAX_DYN];
#endif #endif
...@@ -343,6 +343,7 @@ static int sja1105_init_static_vlan(struct sja1105_private *priv) ...@@ -343,6 +343,7 @@ static int sja1105_init_static_vlan(struct sja1105_private *priv)
{ {
struct sja1105_table *table; struct sja1105_table *table;
struct sja1105_vlan_lookup_entry pvid = { struct sja1105_vlan_lookup_entry pvid = {
.type_entry = SJA1110_VLAN_D_TAG,
.ving_mirr = 0, .ving_mirr = 0,
.vegr_mirr = 0, .vegr_mirr = 0,
.vmemb_port = 0, .vmemb_port = 0,
...@@ -455,6 +456,47 @@ static int sja1105_init_l2_forwarding(struct sja1105_private *priv) ...@@ -455,6 +456,47 @@ static int sja1105_init_l2_forwarding(struct sja1105_private *priv)
l2fwd[ds->num_ports + i].vlan_pmap[j] = i; l2fwd[ds->num_ports + i].vlan_pmap[j] = i;
} }
l2fwd[ds->num_ports + i].type_egrpcp2outputq = true;
}
return 0;
}
static int sja1110_init_pcp_remapping(struct sja1105_private *priv)
{
struct sja1110_pcp_remapping_entry *pcp_remap;
struct dsa_switch *ds = priv->ds;
struct sja1105_table *table;
int port, tc;
table = &priv->static_config.tables[BLK_IDX_PCP_REMAPPING];
/* Nothing to do for SJA1105 */
if (!table->ops->max_entry_count)
return 0;
if (table->entry_count) {
kfree(table->entries);
table->entry_count = 0;
}
table->entries = kcalloc(table->ops->max_entry_count,
table->ops->unpacked_entry_size, GFP_KERNEL);
if (!table->entries)
return -ENOMEM;
table->entry_count = table->ops->max_entry_count;
pcp_remap = table->entries;
/* Repeat the configuration done for vlan_pmap */
for (port = 0; port < ds->num_ports; port++) {
if (dsa_is_unused_port(ds, port))
continue;
for (tc = 0; tc < SJA1105_NUM_TC; tc++)
pcp_remap[port].egrpcp[tc] = tc;
} }
return 0; return 0;
...@@ -777,6 +819,9 @@ static int sja1105_static_config_load(struct sja1105_private *priv) ...@@ -777,6 +819,9 @@ static int sja1105_static_config_load(struct sja1105_private *priv)
if (rc < 0) if (rc < 0)
return rc; return rc;
rc = sja1105_init_avb_params(priv); rc = sja1105_init_avb_params(priv);
if (rc < 0)
return rc;
rc = sja1110_init_pcp_remapping(priv);
if (rc < 0) if (rc < 0)
return rc; return rc;
...@@ -2295,6 +2340,7 @@ sja1105_build_bridge_vlans(struct sja1105_private *priv, ...@@ -2295,6 +2340,7 @@ sja1105_build_bridge_vlans(struct sja1105_private *priv,
new_vlan[match].vlan_bc |= BIT(v->port); new_vlan[match].vlan_bc |= BIT(v->port);
if (!v->untagged) if (!v->untagged)
new_vlan[match].tag_port |= BIT(v->port); new_vlan[match].tag_port |= BIT(v->port);
new_vlan[match].type_entry = SJA1110_VLAN_D_TAG;
} }
return 0; return 0;
...@@ -2317,6 +2363,7 @@ sja1105_build_dsa_8021q_vlans(struct sja1105_private *priv, ...@@ -2317,6 +2363,7 @@ sja1105_build_dsa_8021q_vlans(struct sja1105_private *priv,
new_vlan[match].vlan_bc |= BIT(v->port); new_vlan[match].vlan_bc |= BIT(v->port);
if (!v->untagged) if (!v->untagged)
new_vlan[match].tag_port |= BIT(v->port); new_vlan[match].tag_port |= BIT(v->port);
new_vlan[match].type_entry = SJA1110_VLAN_D_TAG;
} }
return 0; return 0;
...@@ -2377,6 +2424,7 @@ static int sja1105_build_subvlans(struct sja1105_private *priv, ...@@ -2377,6 +2424,7 @@ static int sja1105_build_subvlans(struct sja1105_private *priv,
new_vlan[match].tag_port |= BIT(v->port); new_vlan[match].tag_port |= BIT(v->port);
/* But it's always tagged towards the CPU */ /* But it's always tagged towards the CPU */
new_vlan[match].tag_port |= BIT(upstream); new_vlan[match].tag_port |= BIT(upstream);
new_vlan[match].type_entry = SJA1110_VLAN_D_TAG;
/* The Retagging Table generates packet *clones* with /* The Retagging Table generates packet *clones* with
* the new VLAN. This is a very odd hardware quirk * the new VLAN. This is a very odd hardware quirk
...@@ -2544,6 +2592,7 @@ sja1105_build_crosschip_subvlans(struct sja1105_private *priv, ...@@ -2544,6 +2592,7 @@ sja1105_build_crosschip_subvlans(struct sja1105_private *priv,
if (!tmp->untagged) if (!tmp->untagged)
new_vlan[match].tag_port |= BIT(tmp->port); new_vlan[match].tag_port |= BIT(tmp->port);
new_vlan[match].tag_port |= BIT(upstream); new_vlan[match].tag_port |= BIT(upstream);
new_vlan[match].type_entry = SJA1110_VLAN_D_TAG;
/* Deny egress of @rx_vid towards our front-panel port. /* Deny egress of @rx_vid towards our front-panel port.
* This will force the switch to drop it, and we'll see * This will force the switch to drop it, and we'll see
* only the re-retagged packets (having the original, * only the re-retagged packets (having the original,
...@@ -3684,7 +3733,7 @@ static int sja1105_probe(struct spi_device *spi) ...@@ -3684,7 +3733,7 @@ static int sja1105_probe(struct spi_device *spi)
return -ENOMEM; return -ENOMEM;
ds->dev = dev; ds->dev = dev;
ds->num_ports = SJA1105_MAX_NUM_PORTS; ds->num_ports = priv->info->num_ports;
ds->ops = &sja1105_switch_ops; ds->ops = &sja1105_switch_ops;
ds->priv = priv; ds->priv = priv;
priv->ds = ds; priv->ds = ds;
...@@ -3788,6 +3837,10 @@ static const struct of_device_id sja1105_dt_ids[] = { ...@@ -3788,6 +3837,10 @@ static const struct of_device_id sja1105_dt_ids[] = {
{ .compatible = "nxp,sja1105q", .data = &sja1105q_info }, { .compatible = "nxp,sja1105q", .data = &sja1105q_info },
{ .compatible = "nxp,sja1105r", .data = &sja1105r_info }, { .compatible = "nxp,sja1105r", .data = &sja1105r_info },
{ .compatible = "nxp,sja1105s", .data = &sja1105s_info }, { .compatible = "nxp,sja1105s", .data = &sja1105s_info },
{ .compatible = "nxp,sja1110a", .data = &sja1110a_info },
{ .compatible = "nxp,sja1110b", .data = &sja1110b_info },
{ .compatible = "nxp,sja1110c", .data = &sja1110c_info },
{ .compatible = "nxp,sja1110d", .data = &sja1110d_info },
{ /* sentinel */ }, { /* sentinel */ },
}; };
MODULE_DEVICE_TABLE(of, sja1105_dt_ids); MODULE_DEVICE_TABLE(of, sja1105_dt_ids);
......
This diff is collapsed.
...@@ -9,21 +9,30 @@ ...@@ -9,21 +9,30 @@
#include <linux/types.h> #include <linux/types.h>
#include <asm/types.h> #include <asm/types.h>
#define SJA1105_NUM_PORTS 5
#define SJA1110_NUM_PORTS 11
#define SJA1105_MAX_NUM_PORTS SJA1110_NUM_PORTS
#define SJA1105_NUM_TC 8
#define SJA1105_SIZE_SPI_MSG_HEADER 4 #define SJA1105_SIZE_SPI_MSG_HEADER 4
#define SJA1105_SIZE_SPI_MSG_MAXLEN (64 * 4) #define SJA1105_SIZE_SPI_MSG_MAXLEN (64 * 4)
#define SJA1105_SIZE_DEVICE_ID 4 #define SJA1105_SIZE_DEVICE_ID 4
#define SJA1105_SIZE_TABLE_HEADER 12 #define SJA1105_SIZE_TABLE_HEADER 12
#define SJA1105_SIZE_SCHEDULE_ENTRY 8 #define SJA1105_SIZE_SCHEDULE_ENTRY 8
#define SJA1110_SIZE_SCHEDULE_ENTRY 12
#define SJA1105_SIZE_SCHEDULE_ENTRY_POINTS_ENTRY 4 #define SJA1105_SIZE_SCHEDULE_ENTRY_POINTS_ENTRY 4
#define SJA1110_SIZE_SCHEDULE_ENTRY_POINTS_ENTRY 8
#define SJA1105_SIZE_VL_LOOKUP_ENTRY 12 #define SJA1105_SIZE_VL_LOOKUP_ENTRY 12
#define SJA1105_SIZE_VL_POLICING_ENTRY 8 #define SJA1105_SIZE_VL_POLICING_ENTRY 8
#define SJA1105_SIZE_VL_FORWARDING_ENTRY 4 #define SJA1105_SIZE_VL_FORWARDING_ENTRY 4
#define SJA1105_SIZE_L2_POLICING_ENTRY 8 #define SJA1105_SIZE_L2_POLICING_ENTRY 8
#define SJA1105_SIZE_VLAN_LOOKUP_ENTRY 8 #define SJA1105_SIZE_VLAN_LOOKUP_ENTRY 8
#define SJA1110_SIZE_VLAN_LOOKUP_ENTRY 12
#define SJA1105_SIZE_L2_FORWARDING_ENTRY 8 #define SJA1105_SIZE_L2_FORWARDING_ENTRY 8
#define SJA1105_SIZE_L2_FORWARDING_PARAMS_ENTRY 12 #define SJA1105_SIZE_L2_FORWARDING_PARAMS_ENTRY 12
#define SJA1105_SIZE_RETAGGING_ENTRY 8 #define SJA1105_SIZE_RETAGGING_ENTRY 8
#define SJA1105_SIZE_XMII_PARAMS_ENTRY 4 #define SJA1105_SIZE_XMII_PARAMS_ENTRY 4
#define SJA1110_SIZE_XMII_PARAMS_ENTRY 8
#define SJA1105_SIZE_SCHEDULE_PARAMS_ENTRY 12 #define SJA1105_SIZE_SCHEDULE_PARAMS_ENTRY 12
#define SJA1105_SIZE_SCHEDULE_ENTRY_POINTS_PARAMS_ENTRY 4 #define SJA1105_SIZE_SCHEDULE_ENTRY_POINTS_PARAMS_ENTRY 4
#define SJA1105_SIZE_VL_FORWARDING_PARAMS_ENTRY 12 #define SJA1105_SIZE_VL_FORWARDING_PARAMS_ENTRY 12
...@@ -34,11 +43,15 @@ ...@@ -34,11 +43,15 @@
#define SJA1105ET_SIZE_AVB_PARAMS_ENTRY 12 #define SJA1105ET_SIZE_AVB_PARAMS_ENTRY 12
#define SJA1105ET_SIZE_CBS_ENTRY 16 #define SJA1105ET_SIZE_CBS_ENTRY 16
#define SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY 20 #define SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY 20
#define SJA1110_SIZE_L2_LOOKUP_ENTRY 24
#define SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY 32 #define SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY 32
#define SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_ENTRY 16 #define SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_ENTRY 16
#define SJA1110_SIZE_L2_LOOKUP_PARAMS_ENTRY 28
#define SJA1105PQRS_SIZE_GENERAL_PARAMS_ENTRY 44 #define SJA1105PQRS_SIZE_GENERAL_PARAMS_ENTRY 44
#define SJA1110_SIZE_GENERAL_PARAMS_ENTRY 56
#define SJA1105PQRS_SIZE_AVB_PARAMS_ENTRY 16 #define SJA1105PQRS_SIZE_AVB_PARAMS_ENTRY 16
#define SJA1105PQRS_SIZE_CBS_ENTRY 20 #define SJA1105PQRS_SIZE_CBS_ENTRY 20
#define SJA1110_SIZE_PCP_REMAPPING_ENTRY 4
/* UM10944.pdf Page 11, Table 2. Configuration Blocks */ /* UM10944.pdf Page 11, Table 2. Configuration Blocks */
enum { enum {
...@@ -61,6 +74,7 @@ enum { ...@@ -61,6 +74,7 @@ enum {
BLKID_GENERAL_PARAMS = 0x11, BLKID_GENERAL_PARAMS = 0x11,
BLKID_RETAGGING = 0x12, BLKID_RETAGGING = 0x12,
BLKID_CBS = 0x13, BLKID_CBS = 0x13,
BLKID_PCP_REMAPPING = 0x1C,
BLKID_XMII_PARAMS = 0x4E, BLKID_XMII_PARAMS = 0x4E,
}; };
...@@ -85,6 +99,7 @@ enum sja1105_blk_idx { ...@@ -85,6 +99,7 @@ enum sja1105_blk_idx {
BLK_IDX_RETAGGING, BLK_IDX_RETAGGING,
BLK_IDX_CBS, BLK_IDX_CBS,
BLK_IDX_XMII_PARAMS, BLK_IDX_XMII_PARAMS,
BLK_IDX_PCP_REMAPPING,
BLK_IDX_MAX, BLK_IDX_MAX,
/* Fake block indices that are only valid for dynamic access */ /* Fake block indices that are only valid for dynamic access */
BLK_IDX_MGMT_ROUTE, BLK_IDX_MGMT_ROUTE,
...@@ -93,15 +108,22 @@ enum sja1105_blk_idx { ...@@ -93,15 +108,22 @@ enum sja1105_blk_idx {
}; };
#define SJA1105_MAX_SCHEDULE_COUNT 1024 #define SJA1105_MAX_SCHEDULE_COUNT 1024
#define SJA1110_MAX_SCHEDULE_COUNT 4096
#define SJA1105_MAX_SCHEDULE_ENTRY_POINTS_COUNT 2048 #define SJA1105_MAX_SCHEDULE_ENTRY_POINTS_COUNT 2048
#define SJA1105_MAX_VL_LOOKUP_COUNT 1024 #define SJA1105_MAX_VL_LOOKUP_COUNT 1024
#define SJA1110_MAX_VL_LOOKUP_COUNT 4096
#define SJA1105_MAX_VL_POLICING_COUNT 1024 #define SJA1105_MAX_VL_POLICING_COUNT 1024
#define SJA1110_MAX_VL_POLICING_COUNT 4096
#define SJA1105_MAX_VL_FORWARDING_COUNT 1024 #define SJA1105_MAX_VL_FORWARDING_COUNT 1024
#define SJA1110_MAX_VL_FORWARDING_COUNT 4096
#define SJA1105_MAX_L2_LOOKUP_COUNT 1024 #define SJA1105_MAX_L2_LOOKUP_COUNT 1024
#define SJA1105_MAX_L2_POLICING_COUNT 45 #define SJA1105_MAX_L2_POLICING_COUNT 45
#define SJA1110_MAX_L2_POLICING_COUNT 110
#define SJA1105_MAX_VLAN_LOOKUP_COUNT 4096 #define SJA1105_MAX_VLAN_LOOKUP_COUNT 4096
#define SJA1105_MAX_L2_FORWARDING_COUNT 13 #define SJA1105_MAX_L2_FORWARDING_COUNT 13
#define SJA1110_MAX_L2_FORWARDING_COUNT 19
#define SJA1105_MAX_MAC_CONFIG_COUNT 5 #define SJA1105_MAX_MAC_CONFIG_COUNT 5
#define SJA1110_MAX_MAC_CONFIG_COUNT 11
#define SJA1105_MAX_SCHEDULE_PARAMS_COUNT 1 #define SJA1105_MAX_SCHEDULE_PARAMS_COUNT 1
#define SJA1105_MAX_SCHEDULE_ENTRY_POINTS_PARAMS_COUNT 1 #define SJA1105_MAX_SCHEDULE_ENTRY_POINTS_PARAMS_COUNT 1
#define SJA1105_MAX_VL_FORWARDING_PARAMS_COUNT 1 #define SJA1105_MAX_VL_FORWARDING_PARAMS_COUNT 1
...@@ -113,8 +135,11 @@ enum sja1105_blk_idx { ...@@ -113,8 +135,11 @@ enum sja1105_blk_idx {
#define SJA1105_MAX_AVB_PARAMS_COUNT 1 #define SJA1105_MAX_AVB_PARAMS_COUNT 1
#define SJA1105ET_MAX_CBS_COUNT 10 #define SJA1105ET_MAX_CBS_COUNT 10
#define SJA1105PQRS_MAX_CBS_COUNT 16 #define SJA1105PQRS_MAX_CBS_COUNT 16
#define SJA1110_MAX_CBS_COUNT 80
#define SJA1110_MAX_PCP_REMAPPING_COUNT 11
#define SJA1105_MAX_FRAME_MEMORY 929 #define SJA1105_MAX_FRAME_MEMORY 929
#define SJA1110_MAX_FRAME_MEMORY 1820
#define SJA1105_FRAME_MEMORY_RETAGGING_OVERHEAD 19 #define SJA1105_FRAME_MEMORY_RETAGGING_OVERHEAD 19
#define SJA1105_VL_FRAME_MEMORY 100 #define SJA1105_VL_FRAME_MEMORY 100
...@@ -122,12 +147,26 @@ enum sja1105_blk_idx { ...@@ -122,12 +147,26 @@ enum sja1105_blk_idx {
#define SJA1105T_DEVICE_ID 0x9E00030Eull #define SJA1105T_DEVICE_ID 0x9E00030Eull
#define SJA1105PR_DEVICE_ID 0xAF00030Eull #define SJA1105PR_DEVICE_ID 0xAF00030Eull
#define SJA1105QS_DEVICE_ID 0xAE00030Eull #define SJA1105QS_DEVICE_ID 0xAE00030Eull
#define SJA1110_DEVICE_ID 0xB700030Full
#define SJA1105ET_PART_NO 0x9A83 #define SJA1105ET_PART_NO 0x9A83
#define SJA1105P_PART_NO 0x9A84 #define SJA1105P_PART_NO 0x9A84
#define SJA1105Q_PART_NO 0x9A85 #define SJA1105Q_PART_NO 0x9A85
#define SJA1105R_PART_NO 0x9A86 #define SJA1105R_PART_NO 0x9A86
#define SJA1105S_PART_NO 0x9A87 #define SJA1105S_PART_NO 0x9A87
#define SJA1110A_PART_NO 0x1110
#define SJA1110B_PART_NO 0x1111
#define SJA1110C_PART_NO 0x1112
#define SJA1110D_PART_NO 0x1113
#define SJA1110_ACU 0x1c4400
#define SJA1110_RGU 0x1c6000
#define SJA1110_CGU 0x1c6400
#define SJA1110_SPI_ADDR(x) ((x) / 4)
#define SJA1110_ACU_ADDR(x) (SJA1110_ACU + SJA1110_SPI_ADDR(x))
#define SJA1110_CGU_ADDR(x) (SJA1110_CGU + SJA1110_SPI_ADDR(x))
#define SJA1110_RGU_ADDR(x) (SJA1110_RGU + SJA1110_SPI_ADDR(x))
#define SJA1105_RSV_ADDR 0xffffffffffffffffull #define SJA1105_RSV_ADDR 0xffffffffffffffffull
...@@ -175,6 +214,8 @@ struct sja1105_general_params_entry { ...@@ -175,6 +214,8 @@ struct sja1105_general_params_entry {
u64 egrmirrpcp; u64 egrmirrpcp;
u64 egrmirrdei; u64 egrmirrdei;
u64 replay_port; u64 replay_port;
/* SJA1110 only */
u64 tte_en;
}; };
struct sja1105_schedule_entry_points_entry { struct sja1105_schedule_entry_points_entry {
...@@ -195,6 +236,7 @@ struct sja1105_vlan_lookup_entry { ...@@ -195,6 +236,7 @@ struct sja1105_vlan_lookup_entry {
u64 vlan_bc; u64 vlan_bc;
u64 tag_port; u64 tag_port;
u64 vlanid; u64 vlanid;
u64 type_entry; /* SJA1110 only */
}; };
struct sja1105_l2_lookup_entry { struct sja1105_l2_lookup_entry {
...@@ -207,11 +249,17 @@ struct sja1105_l2_lookup_entry { ...@@ -207,11 +249,17 @@ struct sja1105_l2_lookup_entry {
u64 mask_iotag; u64 mask_iotag;
u64 mask_vlanid; u64 mask_vlanid;
u64 mask_macaddr; u64 mask_macaddr;
u64 mask_srcport;
u64 iotag; u64 iotag;
u64 srcport;
u64 lockeds; u64 lockeds;
union { union {
/* LOCKEDS=1: Static FDB entries */ /* LOCKEDS=1: Static FDB entries */
struct { struct {
/* TSREG is deprecated in SJA1110, TRAP is supported only
* in SJA1110.
*/
u64 trap;
u64 tsreg; u64 tsreg;
u64 mirrvlan; u64 mirrvlan;
u64 takets; u64 takets;
...@@ -227,7 +275,7 @@ struct sja1105_l2_lookup_entry { ...@@ -227,7 +275,7 @@ struct sja1105_l2_lookup_entry {
}; };
struct sja1105_l2_lookup_params_entry { struct sja1105_l2_lookup_params_entry {
u64 maxaddrp[5]; /* P/Q/R/S only */ u64 maxaddrp[SJA1105_MAX_NUM_PORTS]; /* P/Q/R/S only */
u64 start_dynspc; /* P/Q/R/S only */ u64 start_dynspc; /* P/Q/R/S only */
u64 drpnolearn; /* P/Q/R/S only */ u64 drpnolearn; /* P/Q/R/S only */
u64 use_static; /* P/Q/R/S only */ u64 use_static; /* P/Q/R/S only */
...@@ -245,7 +293,9 @@ struct sja1105_l2_forwarding_entry { ...@@ -245,7 +293,9 @@ struct sja1105_l2_forwarding_entry {
u64 bc_domain; u64 bc_domain;
u64 reach_port; u64 reach_port;
u64 fl_domain; u64 fl_domain;
u64 vlan_pmap[8]; /* This is actually max(SJA1105_NUM_TC, SJA1105_MAX_NUM_PORTS) */
u64 vlan_pmap[SJA1105_MAX_NUM_PORTS];
bool type_egrpcp2outputq;
}; };
struct sja1105_l2_forwarding_params_entry { struct sja1105_l2_forwarding_params_entry {
...@@ -300,8 +350,8 @@ struct sja1105_retagging_entry { ...@@ -300,8 +350,8 @@ struct sja1105_retagging_entry {
}; };
struct sja1105_cbs_entry { struct sja1105_cbs_entry {
u64 port; u64 port; /* Not used for SJA1110 */
u64 prio; u64 prio; /* Not used for SJA1110 */
u64 credit_hi; u64 credit_hi;
u64 credit_lo; u64 credit_lo;
u64 send_slope; u64 send_slope;
...@@ -309,8 +359,19 @@ struct sja1105_cbs_entry { ...@@ -309,8 +359,19 @@ struct sja1105_cbs_entry {
}; };
struct sja1105_xmii_params_entry { struct sja1105_xmii_params_entry {
u64 phy_mac[5]; u64 phy_mac[SJA1105_MAX_NUM_PORTS];
u64 xmii_mode[5]; u64 xmii_mode[SJA1105_MAX_NUM_PORTS];
/* The SJA1110 insists being a snowflake, and requires SGMII,
* 2500base-x and internal MII ports connected to the 100base-TX PHY to
* set this bit. We set it unconditionally from the high-level logic,
* and only sja1110_xmii_params_entry_packing writes it to the static
* config. I have no better name for it than "special".
*/
u64 special[SJA1105_MAX_NUM_PORTS];
};
struct sja1110_pcp_remapping_entry {
u64 egrpcp[SJA1105_NUM_TC];
}; };
enum { enum {
...@@ -391,6 +452,7 @@ extern const struct sja1105_table_ops sja1105p_table_ops[BLK_IDX_MAX]; ...@@ -391,6 +452,7 @@ extern const struct sja1105_table_ops sja1105p_table_ops[BLK_IDX_MAX];
extern const struct sja1105_table_ops sja1105q_table_ops[BLK_IDX_MAX]; extern const struct sja1105_table_ops sja1105q_table_ops[BLK_IDX_MAX];
extern const struct sja1105_table_ops sja1105r_table_ops[BLK_IDX_MAX]; extern const struct sja1105_table_ops sja1105r_table_ops[BLK_IDX_MAX];
extern const struct sja1105_table_ops sja1105s_table_ops[BLK_IDX_MAX]; extern const struct sja1105_table_ops sja1105s_table_ops[BLK_IDX_MAX];
extern const struct sja1105_table_ops sja1110_table_ops[BLK_IDX_MAX];
size_t sja1105_table_header_packing(void *buf, void *hdr, enum packing_op op); size_t sja1105_table_header_packing(void *buf, void *hdr, enum packing_op op);
void void
...@@ -438,23 +500,47 @@ void sja1105_packing(void *buf, u64 *val, int start, int end, ...@@ -438,23 +500,47 @@ void sja1105_packing(void *buf, u64 *val, int start, int end,
/* Common implementations for the static and dynamic configs */ /* Common implementations for the static and dynamic configs */
size_t sja1105pqrs_general_params_entry_packing(void *buf, void *entry_ptr, size_t sja1105pqrs_general_params_entry_packing(void *buf, void *entry_ptr,
enum packing_op op); enum packing_op op);
size_t sja1110_general_params_entry_packing(void *buf, void *entry_ptr,
enum packing_op op);
size_t sja1105pqrs_l2_lookup_params_entry_packing(void *buf, void *entry_ptr, size_t sja1105pqrs_l2_lookup_params_entry_packing(void *buf, void *entry_ptr,
enum packing_op op); enum packing_op op);
size_t sja1110_l2_lookup_params_entry_packing(void *buf, void *entry_ptr,
enum packing_op op);
size_t sja1105_l2_forwarding_entry_packing(void *buf, void *entry_ptr, size_t sja1105_l2_forwarding_entry_packing(void *buf, void *entry_ptr,
enum packing_op op); enum packing_op op);
size_t sja1110_l2_forwarding_entry_packing(void *buf, void *entry_ptr,
enum packing_op op);
size_t sja1105pqrs_l2_lookup_entry_packing(void *buf, void *entry_ptr, size_t sja1105pqrs_l2_lookup_entry_packing(void *buf, void *entry_ptr,
enum packing_op op); enum packing_op op);
size_t sja1105et_l2_lookup_entry_packing(void *buf, void *entry_ptr, size_t sja1105et_l2_lookup_entry_packing(void *buf, void *entry_ptr,
enum packing_op op); enum packing_op op);
size_t sja1110_l2_lookup_entry_packing(void *buf, void *entry_ptr,
enum packing_op op);
size_t sja1105_vlan_lookup_entry_packing(void *buf, void *entry_ptr, size_t sja1105_vlan_lookup_entry_packing(void *buf, void *entry_ptr,
enum packing_op op); enum packing_op op);
size_t sja1110_vlan_lookup_entry_packing(void *buf, void *entry_ptr,
enum packing_op op);
size_t sja1105_retagging_entry_packing(void *buf, void *entry_ptr, size_t sja1105_retagging_entry_packing(void *buf, void *entry_ptr,
enum packing_op op); enum packing_op op);
size_t sja1110_retagging_entry_packing(void *buf, void *entry_ptr,
enum packing_op op);
size_t sja1105pqrs_mac_config_entry_packing(void *buf, void *entry_ptr, size_t sja1105pqrs_mac_config_entry_packing(void *buf, void *entry_ptr,
enum packing_op op); enum packing_op op);
size_t sja1110_mac_config_entry_packing(void *buf, void *entry_ptr,
enum packing_op op);
size_t sja1105pqrs_avb_params_entry_packing(void *buf, void *entry_ptr, size_t sja1105pqrs_avb_params_entry_packing(void *buf, void *entry_ptr,
enum packing_op op); enum packing_op op);
size_t sja1105_vl_lookup_entry_packing(void *buf, void *entry_ptr, size_t sja1105_vl_lookup_entry_packing(void *buf, void *entry_ptr,
enum packing_op op); enum packing_op op);
size_t sja1110_vl_lookup_entry_packing(void *buf, void *entry_ptr,
enum packing_op op);
size_t sja1110_vl_policing_entry_packing(void *buf, void *entry_ptr,
enum packing_op op);
size_t sja1110_xmii_params_entry_packing(void *buf, void *entry_ptr,
enum packing_op op);
size_t sja1110_l2_policing_entry_packing(void *buf, void *entry_ptr,
enum packing_op op);
size_t sja1110_l2_forwarding_params_entry_packing(void *buf, void *entry_ptr,
enum packing_op op);
#endif #endif
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