Commit fd5f5ab0 authored by David S. Miller's avatar David S. Miller

Merge branch 'dsa-sja1110'

Vladimir Oltean says:

====================
Add NXP SJA1110 support to the sja1105 DSA driver

The NXP SJA1110 is an automotive Ethernet switch with an embedded Arm
Cortex-M7 microcontroller. The switch has 11 ports (10 external + one
for the DSA-style connection to the microcontroller).
The microcontroller can be disabled and the switch can be controlled
over SPI, a la SJA1105 - this is how this driver handles things.

There are some integrated NXP PHYs (100base-T1 and 100base-TX). Their
initialization is handled by their own PHY drivers, the switch is only
concerned with enabling register accesses to them, by registering two
MDIO buses.

Changes in v3:
- Make sure the VLAN retagging port is enabled and functional
- Dropped SGMII PCS from this series

Changes in v2:
- converted nxp,sja1105 DT bindings to YAML
- registered the PCS MDIO bus and forced auto-probing off for all PHY
  addresses for this bus
- changed the container node name for the 2 MDIO buses from "mdio" to
  "mdios" to avoid matching on the mdio.yaml schema (it's just a
  container node, not an MDIO bus)
- fixed an uninitialized "offset" variable usage in
  sja1110_pcs_mdio_{read,write}
- using the mdiobus_c45_addr macro instead of open-coding that operation
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 173dbbfe 5a8f0974
...@@ -27,10 +27,53 @@ properties: ...@@ -27,10 +27,53 @@ properties:
- nxp,sja1105q - nxp,sja1105q
- nxp,sja1105r - nxp,sja1105r
- nxp,sja1105s - nxp,sja1105s
- nxp,sja1110a
- nxp,sja1110b
- nxp,sja1110c
- nxp,sja1110d
reg: reg:
maxItems: 1 maxItems: 1
# Optional container node for the 2 internal MDIO buses of the SJA1110
# (one for the internal 100base-T1 PHYs and the other for the single
# 100base-TX PHY). The "reg" property does not have physical significance.
# The PHY addresses to port correspondence is as follows: for 100base-T1,
# port 5 has PHY 1, port 6 has PHY 2 etc, while for 100base-TX, port 1 has
# PHY 1.
mdios:
type: object
properties:
'#address-cells':
const: 1
'#size-cells':
const: 0
patternProperties:
"^mdio@[0-1]$":
type: object
allOf:
- $ref: "http://devicetree.org/schemas/net/mdio.yaml#"
properties:
compatible:
oneOf:
- enum:
- nxp,sja1110-base-t1-mdio
- nxp,sja1110-base-tx-mdio
reg:
oneOf:
- enum:
- 0
- 1
required:
- compatible
- reg
required: required:
- compatible - compatible
- reg - reg
......
...@@ -4,6 +4,7 @@ obj-$(CONFIG_NET_DSA_SJA1105) += sja1105.o ...@@ -4,6 +4,7 @@ obj-$(CONFIG_NET_DSA_SJA1105) += sja1105.o
sja1105-objs := \ sja1105-objs := \
sja1105_spi.o \ sja1105_spi.o \
sja1105_main.o \ sja1105_main.o \
sja1105_mdio.o \
sja1105_flower.o \ sja1105_flower.o \
sja1105_ethtool.o \ sja1105_ethtool.o \
sja1105_devlink.o \ sja1105_devlink.o \
......
...@@ -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,
...@@ -70,6 +67,12 @@ struct sja1105_regs { ...@@ -70,6 +67,12 @@ struct sja1105_regs {
u64 rmii_ref_clk[SJA1105_MAX_NUM_PORTS]; u64 rmii_ref_clk[SJA1105_MAX_NUM_PORTS];
u64 rmii_ext_tx_clk[SJA1105_MAX_NUM_PORTS]; u64 rmii_ext_tx_clk[SJA1105_MAX_NUM_PORTS];
u64 stats[__MAX_SJA1105_STATS_AREA][SJA1105_MAX_NUM_PORTS]; u64 stats[__MAX_SJA1105_STATS_AREA][SJA1105_MAX_NUM_PORTS];
u64 mdio_100base_tx;
u64 mdio_100base_t1;
};
struct sja1105_mdio_private {
struct sja1105_private *priv;
}; };
enum { enum {
...@@ -81,6 +84,12 @@ enum { ...@@ -81,6 +84,12 @@ enum {
SJA1105_SPEED_MAX, SJA1105_SPEED_MAX,
}; };
enum sja1105_internal_phy_t {
SJA1105_NO_PHY = 0,
SJA1105_PHY_BASE_TX,
SJA1105_PHY_BASE_T1,
};
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
...@@ -99,6 +108,7 @@ struct sja1105_info { ...@@ -99,6 +108,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;
...@@ -125,6 +135,7 @@ struct sja1105_info { ...@@ -125,6 +135,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];
enum sja1105_internal_phy_t internal_phy[SJA1105_MAX_NUM_PORTS];
const u64 port_speed[SJA1105_SPEED_MAX]; const u64 port_speed[SJA1105_SPEED_MAX];
}; };
...@@ -248,6 +259,8 @@ struct sja1105_private { ...@@ -248,6 +259,8 @@ struct sja1105_private {
enum sja1105_vlan_state vlan_state; enum sja1105_vlan_state vlan_state;
struct devlink_region **regions; struct devlink_region **regions;
struct sja1105_cbs_entry *cbs; struct sja1105_cbs_entry *cbs;
struct mii_bus *mdio_base_t1;
struct mii_bus *mdio_base_tx;
struct sja1105_tagger_data tagger_data; struct sja1105_tagger_data tagger_data;
struct sja1105_ptp_data ptp_data; struct sja1105_ptp_data ptp_data;
struct sja1105_tas_data tas_data; struct sja1105_tas_data tas_data;
...@@ -277,6 +290,10 @@ int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled, ...@@ -277,6 +290,10 @@ int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled,
struct netlink_ext_ack *extack); struct netlink_ext_ack *extack);
void sja1105_frame_memory_partitioning(struct sja1105_private *priv); void sja1105_frame_memory_partitioning(struct sja1105_private *priv);
/* From sja1105_mdio.c */
int sja1105_mdiobus_register(struct dsa_switch *ds);
void sja1105_mdiobus_unregister(struct dsa_switch *ds);
/* From sja1105_devlink.c */ /* From sja1105_devlink.c */
int sja1105_devlink_setup(struct dsa_switch *ds); int sja1105_devlink_setup(struct dsa_switch *ds);
void sja1105_devlink_teardown(struct dsa_switch *ds); void sja1105_devlink_teardown(struct dsa_switch *ds);
...@@ -310,6 +327,10 @@ extern const struct sja1105_info sja1105p_info; ...@@ -310,6 +327,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 +347,10 @@ typedef enum { ...@@ -326,8 +347,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 +371,18 @@ enum sja1105_iotag { ...@@ -348,6 +371,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
...@@ -168,6 +168,15 @@ static int sja1105_init_mii_settings(struct sja1105_private *priv) ...@@ -168,6 +168,15 @@ static int sja1105_init_mii_settings(struct sja1105_private *priv)
continue; continue;
switch (priv->phy_mode[i]) { switch (priv->phy_mode[i]) {
case PHY_INTERFACE_MODE_INTERNAL:
if (priv->info->internal_phy[i] == SJA1105_NO_PHY)
goto unsupported;
mii->xmii_mode[i] = XMII_MODE_MII;
if (priv->info->internal_phy[i] == SJA1105_PHY_BASE_TX)
mii->special[i] = true;
break;
case PHY_INTERFACE_MODE_REVMII: case PHY_INTERFACE_MODE_REVMII:
role = XMII_PHY; role = XMII_PHY;
fallthrough; fallthrough;
...@@ -343,6 +352,7 @@ static int sja1105_init_static_vlan(struct sja1105_private *priv) ...@@ -343,6 +352,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 +465,47 @@ static int sja1105_init_l2_forwarding(struct sja1105_private *priv) ...@@ -455,6 +465,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;
...@@ -523,6 +574,60 @@ void sja1105_frame_memory_partitioning(struct sja1105_private *priv) ...@@ -523,6 +574,60 @@ void sja1105_frame_memory_partitioning(struct sja1105_private *priv)
vl_fwd_params->partspc[0] = SJA1105_VL_FRAME_MEMORY; vl_fwd_params->partspc[0] = SJA1105_VL_FRAME_MEMORY;
} }
/* SJA1110 TDMACONFIGIDX values:
*
* | 100 Mbps ports | 1Gbps ports | 2.5Gbps ports | Disabled ports
* -----+----------------+---------------+---------------+---------------
* 0 | 0, [5:10] | [1:2] | [3:4] | retag
* 1 |0, [5:10], retag| [1:2] | [3:4] | -
* 2 | 0, [5:10] | [1:3], retag | 4 | -
* 3 | 0, [5:10] |[1:2], 4, retag| 3 | -
* 4 | 0, 2, [5:10] | 1, retag | [3:4] | -
* 5 | 0, 1, [5:10] | 2, retag | [3:4] | -
* 14 | 0, [5:10] | [1:4], retag | - | -
* 15 | [5:10] | [0:4], retag | - | -
*/
static void sja1110_select_tdmaconfigidx(struct sja1105_private *priv)
{
struct sja1105_general_params_entry *general_params;
struct sja1105_table *table;
bool port_1_is_base_tx;
bool port_3_is_2500;
bool port_4_is_2500;
u64 tdmaconfigidx;
if (priv->info->device_id != SJA1110_DEVICE_ID)
return;
table = &priv->static_config.tables[BLK_IDX_GENERAL_PARAMS];
general_params = table->entries;
/* All the settings below are "as opposed to SGMII", which is the
* other pinmuxing option.
*/
port_1_is_base_tx = priv->phy_mode[1] == PHY_INTERFACE_MODE_INTERNAL;
port_3_is_2500 = priv->phy_mode[3] == PHY_INTERFACE_MODE_2500BASEX;
port_4_is_2500 = priv->phy_mode[4] == PHY_INTERFACE_MODE_2500BASEX;
if (port_1_is_base_tx)
/* Retagging port will operate at 1 Gbps */
tdmaconfigidx = 5;
else if (port_3_is_2500 && port_4_is_2500)
/* Retagging port will operate at 100 Mbps */
tdmaconfigidx = 1;
else if (port_3_is_2500)
/* Retagging port will operate at 1 Gbps */
tdmaconfigidx = 3;
else if (port_4_is_2500)
/* Retagging port will operate at 1 Gbps */
tdmaconfigidx = 2;
else
/* Retagging port will operate at 1 Gbps */
tdmaconfigidx = 14;
general_params->tdmaconfigidx = tdmaconfigidx;
}
static int sja1105_init_general_params(struct sja1105_private *priv) static int sja1105_init_general_params(struct sja1105_private *priv)
{ {
struct sja1105_general_params_entry default_general_params = { struct sja1105_general_params_entry default_general_params = {
...@@ -598,6 +703,8 @@ static int sja1105_init_general_params(struct sja1105_private *priv) ...@@ -598,6 +703,8 @@ static int sja1105_init_general_params(struct sja1105_private *priv)
((struct sja1105_general_params_entry *)table->entries)[0] = ((struct sja1105_general_params_entry *)table->entries)[0] =
default_general_params; default_general_params;
sja1110_select_tdmaconfigidx(priv);
return 0; return 0;
} }
...@@ -777,6 +884,9 @@ static int sja1105_static_config_load(struct sja1105_private *priv) ...@@ -777,6 +884,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 +2405,7 @@ sja1105_build_bridge_vlans(struct sja1105_private *priv, ...@@ -2295,6 +2405,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 +2428,7 @@ sja1105_build_dsa_8021q_vlans(struct sja1105_private *priv, ...@@ -2317,6 +2428,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 +2489,7 @@ static int sja1105_build_subvlans(struct sja1105_private *priv, ...@@ -2377,6 +2489,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 +2657,7 @@ sja1105_build_crosschip_subvlans(struct sja1105_private *priv, ...@@ -2544,6 +2657,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,
...@@ -3004,11 +3118,19 @@ static int sja1105_setup(struct dsa_switch *ds) ...@@ -3004,11 +3118,19 @@ static int sja1105_setup(struct dsa_switch *ds)
dev_err(ds->dev, "Failed to register PTP clock: %d\n", rc); dev_err(ds->dev, "Failed to register PTP clock: %d\n", rc);
return rc; return rc;
} }
rc = sja1105_mdiobus_register(ds);
if (rc < 0) {
dev_err(ds->dev, "Failed to register MDIO bus: %pe\n",
ERR_PTR(rc));
goto out_ptp_clock_unregister;
}
/* Create and send configuration down to device */ /* Create and send configuration down to device */
rc = sja1105_static_config_load(priv); rc = sja1105_static_config_load(priv);
if (rc < 0) { if (rc < 0) {
dev_err(ds->dev, "Failed to load static config: %d\n", rc); dev_err(ds->dev, "Failed to load static config: %d\n", rc);
goto out_ptp_clock_unregister; goto out_mdiobus_unregister;
} }
/* Configure the CGU (PHY link modes and speeds) */ /* Configure the CGU (PHY link modes and speeds) */
rc = priv->info->clocking_setup(priv); rc = priv->info->clocking_setup(priv);
...@@ -3051,6 +3173,8 @@ static int sja1105_setup(struct dsa_switch *ds) ...@@ -3051,6 +3173,8 @@ static int sja1105_setup(struct dsa_switch *ds)
out_devlink_teardown: out_devlink_teardown:
sja1105_devlink_teardown(ds); sja1105_devlink_teardown(ds);
out_mdiobus_unregister:
sja1105_mdiobus_unregister(ds);
out_ptp_clock_unregister: out_ptp_clock_unregister:
sja1105_ptp_clock_unregister(ds); sja1105_ptp_clock_unregister(ds);
out_static_config_free: out_static_config_free:
...@@ -3684,7 +3808,7 @@ static int sja1105_probe(struct spi_device *spi) ...@@ -3684,7 +3808,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 +3912,10 @@ static const struct of_device_id sja1105_dt_ids[] = { ...@@ -3788,6 +3912,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);
......
// SPDX-License-Identifier: GPL-2.0
/* Copyright 2021, NXP Semiconductors
*/
#include <linux/of_mdio.h>
#include "sja1105.h"
enum sja1105_mdio_opcode {
SJA1105_C45_ADDR = 0,
SJA1105_C22 = 1,
SJA1105_C45_DATA = 2,
SJA1105_C45_DATA_AUTOINC = 3,
};
static u64 sja1105_base_t1_encode_addr(struct sja1105_private *priv,
int phy, enum sja1105_mdio_opcode op,
int xad)
{
const struct sja1105_regs *regs = priv->info->regs;
return regs->mdio_100base_t1 | (phy << 7) | (op << 5) | (xad << 0);
}
static int sja1105_base_t1_mdio_read(struct mii_bus *bus, int phy, int reg)
{
struct sja1105_mdio_private *mdio_priv = bus->priv;
struct sja1105_private *priv = mdio_priv->priv;
u64 addr;
u32 tmp;
int rc;
if (reg & MII_ADDR_C45) {
u16 mmd = (reg >> MII_DEVADDR_C45_SHIFT) & 0x1f;
addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C45_ADDR,
mmd);
tmp = reg & MII_REGADDR_C45_MASK;
rc = sja1105_xfer_u32(priv, SPI_WRITE, addr, &tmp, NULL);
if (rc < 0)
return rc;
addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C45_DATA,
mmd);
rc = sja1105_xfer_u32(priv, SPI_READ, addr, &tmp, NULL);
if (rc < 0)
return rc;
return tmp & 0xffff;
}
/* Clause 22 read */
addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C22, reg & 0x1f);
rc = sja1105_xfer_u32(priv, SPI_READ, addr, &tmp, NULL);
if (rc < 0)
return rc;
return tmp & 0xffff;
}
static int sja1105_base_t1_mdio_write(struct mii_bus *bus, int phy, int reg,
u16 val)
{
struct sja1105_mdio_private *mdio_priv = bus->priv;
struct sja1105_private *priv = mdio_priv->priv;
u64 addr;
u32 tmp;
int rc;
if (reg & MII_ADDR_C45) {
u16 mmd = (reg >> MII_DEVADDR_C45_SHIFT) & 0x1f;
addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C45_ADDR,
mmd);
tmp = reg & MII_REGADDR_C45_MASK;
rc = sja1105_xfer_u32(priv, SPI_WRITE, addr, &tmp, NULL);
if (rc < 0)
return rc;
addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C45_DATA,
mmd);
tmp = val & 0xffff;
rc = sja1105_xfer_u32(priv, SPI_WRITE, addr, &tmp, NULL);
if (rc < 0)
return rc;
return 0;
}
/* Clause 22 write */
addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C22, reg & 0x1f);
tmp = val & 0xffff;
return sja1105_xfer_u32(priv, SPI_WRITE, addr, &tmp, NULL);
}
static int sja1105_base_tx_mdio_read(struct mii_bus *bus, int phy, int reg)
{
struct sja1105_mdio_private *mdio_priv = bus->priv;
struct sja1105_private *priv = mdio_priv->priv;
const struct sja1105_regs *regs = priv->info->regs;
u32 tmp;
int rc;
rc = sja1105_xfer_u32(priv, SPI_READ, regs->mdio_100base_tx + reg,
&tmp, NULL);
if (rc < 0)
return rc;
return tmp & 0xffff;
}
static int sja1105_base_tx_mdio_write(struct mii_bus *bus, int phy, int reg,
u16 val)
{
struct sja1105_mdio_private *mdio_priv = bus->priv;
struct sja1105_private *priv = mdio_priv->priv;
const struct sja1105_regs *regs = priv->info->regs;
u32 tmp = val;
return sja1105_xfer_u32(priv, SPI_WRITE, regs->mdio_100base_tx + reg,
&tmp, NULL);
}
static int sja1105_mdiobus_base_tx_register(struct sja1105_private *priv,
struct device_node *mdio_node)
{
struct sja1105_mdio_private *mdio_priv;
struct device_node *np;
struct mii_bus *bus;
int rc = 0;
np = of_find_compatible_node(mdio_node, NULL,
"nxp,sja1110-base-tx-mdio");
if (!np)
return 0;
if (!of_device_is_available(np))
goto out_put_np;
bus = mdiobus_alloc_size(sizeof(*mdio_priv));
if (!bus) {
rc = -ENOMEM;
goto out_put_np;
}
bus->name = "SJA1110 100base-TX MDIO bus";
snprintf(bus->id, MII_BUS_ID_SIZE, "%s-base-tx",
dev_name(priv->ds->dev));
bus->read = sja1105_base_tx_mdio_read;
bus->write = sja1105_base_tx_mdio_write;
bus->parent = priv->ds->dev;
mdio_priv = bus->priv;
mdio_priv->priv = priv;
rc = of_mdiobus_register(bus, np);
if (rc) {
mdiobus_free(bus);
goto out_put_np;
}
priv->mdio_base_tx = bus;
out_put_np:
of_node_put(np);
return 0;
}
static void sja1105_mdiobus_base_tx_unregister(struct sja1105_private *priv)
{
if (!priv->mdio_base_tx)
return;
mdiobus_unregister(priv->mdio_base_tx);
mdiobus_free(priv->mdio_base_tx);
priv->mdio_base_tx = NULL;
}
static int sja1105_mdiobus_base_t1_register(struct sja1105_private *priv,
struct device_node *mdio_node)
{
struct sja1105_mdio_private *mdio_priv;
struct device_node *np;
struct mii_bus *bus;
int rc = 0;
np = of_find_compatible_node(mdio_node, NULL,
"nxp,sja1110-base-t1-mdio");
if (!np)
return 0;
if (!of_device_is_available(np))
goto out_put_np;
bus = mdiobus_alloc_size(sizeof(*mdio_priv));
if (!bus) {
rc = -ENOMEM;
goto out_put_np;
}
bus->name = "SJA1110 100base-T1 MDIO bus";
snprintf(bus->id, MII_BUS_ID_SIZE, "%s-base-t1",
dev_name(priv->ds->dev));
bus->read = sja1105_base_t1_mdio_read;
bus->write = sja1105_base_t1_mdio_write;
bus->parent = priv->ds->dev;
mdio_priv = bus->priv;
mdio_priv->priv = priv;
rc = of_mdiobus_register(bus, np);
if (rc) {
mdiobus_free(bus);
goto out_put_np;
}
priv->mdio_base_t1 = bus;
out_put_np:
of_node_put(np);
return rc;
}
static void sja1105_mdiobus_base_t1_unregister(struct sja1105_private *priv)
{
if (!priv->mdio_base_t1)
return;
mdiobus_unregister(priv->mdio_base_t1);
mdiobus_free(priv->mdio_base_t1);
priv->mdio_base_t1 = NULL;
}
int sja1105_mdiobus_register(struct dsa_switch *ds)
{
struct sja1105_private *priv = ds->priv;
const struct sja1105_regs *regs = priv->info->regs;
struct device_node *switch_node = ds->dev->of_node;
struct device_node *mdio_node;
int rc;
mdio_node = of_get_child_by_name(switch_node, "mdios");
if (!mdio_node)
return 0;
if (!of_device_is_available(mdio_node))
goto out_put_mdio_node;
if (regs->mdio_100base_tx != SJA1105_RSV_ADDR) {
rc = sja1105_mdiobus_base_tx_register(priv, mdio_node);
if (rc)
goto err_put_mdio_node;
}
if (regs->mdio_100base_t1 != SJA1105_RSV_ADDR) {
rc = sja1105_mdiobus_base_t1_register(priv, mdio_node);
if (rc)
goto err_free_base_tx_mdiobus;
}
out_put_mdio_node:
of_node_put(mdio_node);
return 0;
err_free_base_tx_mdiobus:
sja1105_mdiobus_base_tx_unregister(priv);
err_put_mdio_node:
of_node_put(mdio_node);
return rc;
}
void sja1105_mdiobus_unregister(struct dsa_switch *ds)
{
struct sja1105_private *priv = ds->priv;
sja1105_mdiobus_base_t1_unregister(priv);
sja1105_mdiobus_base_tx_unregister(priv);
}
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,9 @@ struct sja1105_general_params_entry { ...@@ -175,6 +214,9 @@ struct sja1105_general_params_entry {
u64 egrmirrpcp; u64 egrmirrpcp;
u64 egrmirrdei; u64 egrmirrdei;
u64 replay_port; u64 replay_port;
/* SJA1110 only */
u64 tte_en;
u64 tdmaconfigidx;
}; };
struct sja1105_schedule_entry_points_entry { struct sja1105_schedule_entry_points_entry {
...@@ -195,6 +237,7 @@ struct sja1105_vlan_lookup_entry { ...@@ -195,6 +237,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 +250,17 @@ struct sja1105_l2_lookup_entry { ...@@ -207,11 +250,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 +276,7 @@ struct sja1105_l2_lookup_entry { ...@@ -227,7 +276,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 +294,9 @@ struct sja1105_l2_forwarding_entry { ...@@ -245,7 +294,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 +351,8 @@ struct sja1105_retagging_entry { ...@@ -300,8 +351,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 +360,19 @@ struct sja1105_cbs_entry { ...@@ -309,8 +360,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 +453,7 @@ extern const struct sja1105_table_ops sja1105p_table_ops[BLK_IDX_MAX]; ...@@ -391,6 +453,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 +501,47 @@ void sja1105_packing(void *buf, u64 *val, int start, int end, ...@@ -438,23 +501,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