From 3e77e59bf8cf105d64f70133e41c38daf482acc3 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Tue, 8 Jun 2021 12:25:36 +0300 Subject: 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: Vladimir Oltean Signed-off-by: David S. Miller --- drivers/net/dsa/sja1105/sja1105_spi.c | 252 ++++++++++++++++++++++++++++++++++ 1 file changed, 252 insertions(+) (limited to 'drivers/net/dsa/sja1105/sja1105_spi.c') diff --git a/drivers/net/dsa/sja1105/sja1105_spi.c b/drivers/net/dsa/sja1105/sja1105_spi.c index 786c16a77e46..187c9fbbd397 100644 --- a/drivers/net/dsa/sja1105/sja1105_spi.c +++ b/drivers/net/dsa/sja1105/sja1105_spi.c @@ -193,6 +193,16 @@ static int sja1105pqrs_reset_cmd(struct dsa_switch *ds) return sja1105_xfer_u32(priv, SPI_WRITE, regs->rgu, &cold_reset, NULL); } +static int sja1110_reset_cmd(struct dsa_switch *ds) +{ + struct sja1105_private *priv = ds->priv; + const struct sja1105_regs *regs = priv->info->regs; + u32 switch_reset = BIT(20); + + /* Switch core reset */ + return sja1105_xfer_u32(priv, SPI_WRITE, regs->rgu, &switch_reset, NULL); +} + int sja1105_inhibit_tx(const struct sja1105_private *priv, unsigned long port_bitmap, bool tx_inhibited) { @@ -465,6 +475,88 @@ static struct sja1105_regs sja1105pqrs_regs = { .ptpsyncts = 0x1F, }; +static struct sja1105_regs sja1110_regs = { + .device_id = SJA1110_SPI_ADDR(0x0), + .prod_id = SJA1110_ACU_ADDR(0xf00), + .status = SJA1110_SPI_ADDR(0x4), + .port_control = SJA1110_SPI_ADDR(0x50), /* actually INHIB_TX */ + .vl_status = 0x10000, + .config = 0x020000, + .rgu = SJA1110_RGU_ADDR(0x100), /* Reset Control Register 0 */ + /* Ports 2 and 3 are capable of xMII, but there isn't anything to + * configure in the CGU/ACU for them. + */ + .pad_mii_tx = {SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, + SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, + SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, + SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, + SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, + SJA1105_RSV_ADDR}, + .pad_mii_rx = {SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, + SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, + SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, + SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, + SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, + SJA1105_RSV_ADDR}, + .pad_mii_id = {SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, + SJA1110_ACU_ADDR(0x18), SJA1110_ACU_ADDR(0x28), + SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, + SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, + SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, + SJA1105_RSV_ADDR}, + .rmii_pll1 = SJA1105_RSV_ADDR, + .cgu_idiv = {SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, + SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, + SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, + SJA1105_RSV_ADDR, SJA1105_RSV_ADDR}, + .stats[MAC] = {0x200, 0x202, 0x204, 0x206, 0x208, 0x20a, + 0x20c, 0x20e, 0x210, 0x212, 0x214}, + .stats[HL1] = {0x400, 0x410, 0x420, 0x430, 0x440, 0x450, + 0x460, 0x470, 0x480, 0x490, 0x4a0}, + .stats[HL2] = {0x600, 0x610, 0x620, 0x630, 0x640, 0x650, + 0x660, 0x670, 0x680, 0x690, 0x6a0}, + .stats[ETHER] = {0x1400, 0x1418, 0x1430, 0x1448, 0x1460, 0x1478, + 0x1490, 0x14a8, 0x14c0, 0x14d8, 0x14f0}, + .mii_tx_clk = {SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, + SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, + SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, + SJA1105_RSV_ADDR, SJA1105_RSV_ADDR}, + .mii_rx_clk = {SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, + SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, + SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, + SJA1105_RSV_ADDR, SJA1105_RSV_ADDR}, + .mii_ext_tx_clk = {SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, + SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, + SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, + SJA1105_RSV_ADDR, SJA1105_RSV_ADDR}, + .mii_ext_rx_clk = {SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, + SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, + SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, + SJA1105_RSV_ADDR, SJA1105_RSV_ADDR}, + .rgmii_tx_clk = {SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, + SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, + SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, + SJA1105_RSV_ADDR, SJA1105_RSV_ADDR}, + .rmii_ref_clk = {SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, + SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, + SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, + SJA1105_RSV_ADDR, SJA1105_RSV_ADDR}, + .rmii_ext_tx_clk = {SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, + SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, + SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, + SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, + SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, + SJA1105_RSV_ADDR}, + .ptpschtm = SJA1110_SPI_ADDR(0x54), + .ptppinst = SJA1110_SPI_ADDR(0x5c), + .ptppindur = SJA1110_SPI_ADDR(0x64), + .ptp_control = SJA1110_SPI_ADDR(0x68), + .ptpclkval = SJA1110_SPI_ADDR(0x6c), + .ptpclkrate = SJA1110_SPI_ADDR(0x74), + .ptpclkcorp = SJA1110_SPI_ADDR(0x80), + .ptpsyncts = SJA1110_SPI_ADDR(0x84), +}; + const struct sja1105_info sja1105e_info = { .device_id = SJA1105E_DEVICE_ID, .part_no = SJA1105ET_PART_NO, @@ -475,6 +567,7 @@ const struct sja1105_info sja1105e_info = { .ptp_ts_bits = 24, .ptpegr_ts_bytes = 4, .max_frame_mem = SJA1105_MAX_FRAME_MEMORY, + .num_ports = SJA1105_NUM_PORTS, .num_cbs_shapers = SJA1105ET_MAX_CBS_COUNT, .reset_cmd = sja1105et_reset_cmd, .fdb_add_cmd = sja1105et_fdb_add, @@ -505,6 +598,7 @@ const struct sja1105_info sja1105t_info = { .ptp_ts_bits = 24, .ptpegr_ts_bytes = 4, .max_frame_mem = SJA1105_MAX_FRAME_MEMORY, + .num_ports = SJA1105_NUM_PORTS, .num_cbs_shapers = SJA1105ET_MAX_CBS_COUNT, .reset_cmd = sja1105et_reset_cmd, .fdb_add_cmd = sja1105et_fdb_add, @@ -535,6 +629,7 @@ const struct sja1105_info sja1105p_info = { .ptp_ts_bits = 32, .ptpegr_ts_bytes = 8, .max_frame_mem = SJA1105_MAX_FRAME_MEMORY, + .num_ports = SJA1105_NUM_PORTS, .num_cbs_shapers = SJA1105PQRS_MAX_CBS_COUNT, .setup_rgmii_delay = sja1105pqrs_setup_rgmii_delay, .reset_cmd = sja1105pqrs_reset_cmd, @@ -566,6 +661,7 @@ const struct sja1105_info sja1105q_info = { .ptp_ts_bits = 32, .ptpegr_ts_bytes = 8, .max_frame_mem = SJA1105_MAX_FRAME_MEMORY, + .num_ports = SJA1105_NUM_PORTS, .num_cbs_shapers = SJA1105PQRS_MAX_CBS_COUNT, .setup_rgmii_delay = sja1105pqrs_setup_rgmii_delay, .reset_cmd = sja1105pqrs_reset_cmd, @@ -597,6 +693,7 @@ const struct sja1105_info sja1105r_info = { .ptp_ts_bits = 32, .ptpegr_ts_bytes = 8, .max_frame_mem = SJA1105_MAX_FRAME_MEMORY, + .num_ports = SJA1105_NUM_PORTS, .num_cbs_shapers = SJA1105PQRS_MAX_CBS_COUNT, .setup_rgmii_delay = sja1105pqrs_setup_rgmii_delay, .reset_cmd = sja1105pqrs_reset_cmd, @@ -630,6 +727,7 @@ const struct sja1105_info sja1105s_info = { .ptp_ts_bits = 32, .ptpegr_ts_bytes = 8, .max_frame_mem = SJA1105_MAX_FRAME_MEMORY, + .num_ports = SJA1105_NUM_PORTS, .num_cbs_shapers = SJA1105PQRS_MAX_CBS_COUNT, .setup_rgmii_delay = sja1105pqrs_setup_rgmii_delay, .reset_cmd = sja1105pqrs_reset_cmd, @@ -650,3 +748,157 @@ const struct sja1105_info sja1105s_info = { .supports_sgmii = {false, false, false, false, true}, .name = "SJA1105S", }; + +const struct sja1105_info sja1110a_info = { + .device_id = SJA1110_DEVICE_ID, + .part_no = SJA1110A_PART_NO, + .static_ops = sja1110_table_ops, + .dyn_ops = sja1110_dyn_ops, + .regs = &sja1110_regs, + .qinq_tpid = ETH_P_8021AD, + .can_limit_mcast_flood = true, + .ptp_ts_bits = 32, + .ptpegr_ts_bytes = 8, + .max_frame_mem = SJA1110_MAX_FRAME_MEMORY, + .num_ports = SJA1110_NUM_PORTS, + .num_cbs_shapers = SJA1110_MAX_CBS_COUNT, + .setup_rgmii_delay = sja1110_setup_rgmii_delay, + .reset_cmd = sja1110_reset_cmd, + .fdb_add_cmd = sja1105pqrs_fdb_add, + .fdb_del_cmd = sja1105pqrs_fdb_del, + .ptp_cmd_packing = sja1105pqrs_ptp_cmd_packing, + .clocking_setup = sja1110_clocking_setup, + .port_speed = { + [SJA1105_SPEED_AUTO] = 0, + [SJA1105_SPEED_10MBPS] = 4, + [SJA1105_SPEED_100MBPS] = 3, + [SJA1105_SPEED_1000MBPS] = 2, + [SJA1105_SPEED_2500MBPS] = 1, + }, + .supports_mii = {true, true, true, true, false, + true, true, true, true, true, true}, + .supports_rmii = {false, false, true, true, false, + false, false, false, false, false, false}, + .supports_rgmii = {false, false, true, true, false, + false, false, false, false, false, false}, + .supports_sgmii = {false, true, true, true, true, + false, false, false, false, false, false}, + .supports_2500basex = {false, false, false, true, true, + false, false, false, false, false, false}, + .name = "SJA1110A", +}; + +const struct sja1105_info sja1110b_info = { + .device_id = SJA1110_DEVICE_ID, + .part_no = SJA1110B_PART_NO, + .static_ops = sja1110_table_ops, + .dyn_ops = sja1110_dyn_ops, + .regs = &sja1110_regs, + .qinq_tpid = ETH_P_8021AD, + .can_limit_mcast_flood = true, + .ptp_ts_bits = 32, + .ptpegr_ts_bytes = 8, + .max_frame_mem = SJA1110_MAX_FRAME_MEMORY, + .num_ports = SJA1110_NUM_PORTS, + .num_cbs_shapers = SJA1110_MAX_CBS_COUNT, + .setup_rgmii_delay = sja1110_setup_rgmii_delay, + .reset_cmd = sja1110_reset_cmd, + .fdb_add_cmd = sja1105pqrs_fdb_add, + .fdb_del_cmd = sja1105pqrs_fdb_del, + .ptp_cmd_packing = sja1105pqrs_ptp_cmd_packing, + .clocking_setup = sja1110_clocking_setup, + .port_speed = { + [SJA1105_SPEED_AUTO] = 0, + [SJA1105_SPEED_10MBPS] = 4, + [SJA1105_SPEED_100MBPS] = 3, + [SJA1105_SPEED_1000MBPS] = 2, + [SJA1105_SPEED_2500MBPS] = 1, + }, + .supports_mii = {true, true, true, true, false, + true, true, true, true, true, false}, + .supports_rmii = {false, false, true, true, false, + false, false, false, false, false, false}, + .supports_rgmii = {false, false, true, true, false, + false, false, false, false, false, false}, + .supports_sgmii = {false, false, false, true, true, + false, false, false, false, false, false}, + .supports_2500basex = {false, false, false, true, true, + false, false, false, false, false, false}, + .name = "SJA1110B", +}; + +const struct sja1105_info sja1110c_info = { + .device_id = SJA1110_DEVICE_ID, + .part_no = SJA1110C_PART_NO, + .static_ops = sja1110_table_ops, + .dyn_ops = sja1110_dyn_ops, + .regs = &sja1110_regs, + .qinq_tpid = ETH_P_8021AD, + .can_limit_mcast_flood = true, + .ptp_ts_bits = 32, + .ptpegr_ts_bytes = 8, + .max_frame_mem = SJA1110_MAX_FRAME_MEMORY, + .num_ports = SJA1110_NUM_PORTS, + .num_cbs_shapers = SJA1110_MAX_CBS_COUNT, + .setup_rgmii_delay = sja1110_setup_rgmii_delay, + .reset_cmd = sja1110_reset_cmd, + .fdb_add_cmd = sja1105pqrs_fdb_add, + .fdb_del_cmd = sja1105pqrs_fdb_del, + .ptp_cmd_packing = sja1105pqrs_ptp_cmd_packing, + .clocking_setup = sja1110_clocking_setup, + .port_speed = { + [SJA1105_SPEED_AUTO] = 0, + [SJA1105_SPEED_10MBPS] = 4, + [SJA1105_SPEED_100MBPS] = 3, + [SJA1105_SPEED_1000MBPS] = 2, + [SJA1105_SPEED_2500MBPS] = 1, + }, + .supports_mii = {true, true, true, true, false, + true, true, true, false, false, false}, + .supports_rmii = {false, false, true, true, false, + false, false, false, false, false, false}, + .supports_rgmii = {false, false, true, true, false, + false, false, false, false, false, false}, + .supports_sgmii = {false, false, false, false, true, + false, false, false, false, false, false}, + .supports_2500basex = {false, false, false, false, true, + false, false, false, false, false, false}, + .name = "SJA1110C", +}; + +const struct sja1105_info sja1110d_info = { + .device_id = SJA1110_DEVICE_ID, + .part_no = SJA1110D_PART_NO, + .static_ops = sja1110_table_ops, + .dyn_ops = sja1110_dyn_ops, + .regs = &sja1110_regs, + .qinq_tpid = ETH_P_8021AD, + .can_limit_mcast_flood = true, + .ptp_ts_bits = 32, + .ptpegr_ts_bytes = 8, + .max_frame_mem = SJA1110_MAX_FRAME_MEMORY, + .num_ports = SJA1110_NUM_PORTS, + .num_cbs_shapers = SJA1110_MAX_CBS_COUNT, + .setup_rgmii_delay = sja1110_setup_rgmii_delay, + .reset_cmd = sja1110_reset_cmd, + .fdb_add_cmd = sja1105pqrs_fdb_add, + .fdb_del_cmd = sja1105pqrs_fdb_del, + .ptp_cmd_packing = sja1105pqrs_ptp_cmd_packing, + .clocking_setup = sja1110_clocking_setup, + .port_speed = { + [SJA1105_SPEED_AUTO] = 0, + [SJA1105_SPEED_10MBPS] = 4, + [SJA1105_SPEED_100MBPS] = 3, + [SJA1105_SPEED_1000MBPS] = 2, + [SJA1105_SPEED_2500MBPS] = 1, + }, + .supports_mii = {true, false, true, false, false, + true, true, true, false, false, false}, + .supports_rmii = {false, false, true, false, false, + false, false, false, false, false, false}, + .supports_rgmii = {false, false, true, false, false, + false, false, false, false, false, false}, + .supports_sgmii = {false, true, true, true, true, + false, false, false, false, false, false}, + .name = "SJA1110D", +}; -- cgit v1.2.3-59-g8ed1b