diff options
Diffstat (limited to 'drivers/net/dsa')
-rw-r--r-- | drivers/net/dsa/sja1105/sja1105.h | 16 | ||||
-rw-r--r-- | drivers/net/dsa/sja1105/sja1105_clocking.c | 65 | ||||
-rw-r--r-- | drivers/net/dsa/sja1105/sja1105_dynamic_config.c | 12 | ||||
-rw-r--r-- | drivers/net/dsa/sja1105/sja1105_ethtool.c | 16 | ||||
-rw-r--r-- | drivers/net/dsa/sja1105/sja1105_main.c | 106 | ||||
-rw-r--r-- | drivers/net/dsa/sja1105/sja1105_ptp.c | 17 | ||||
-rw-r--r-- | drivers/net/dsa/sja1105/sja1105_spi.c | 97 |
7 files changed, 202 insertions, 127 deletions
diff --git a/drivers/net/dsa/sja1105/sja1105.h b/drivers/net/dsa/sja1105/sja1105.h index e53e494c22e0..8681ff9d1a76 100644 --- a/drivers/net/dsa/sja1105/sja1105.h +++ b/drivers/net/dsa/sja1105/sja1105.h @@ -127,15 +127,13 @@ typedef enum { int sja1105_static_config_reload(struct sja1105_private *priv); /* From sja1105_spi.c */ -int sja1105_spi_send_packed_buf(const struct sja1105_private *priv, - sja1105_spi_rw_mode_t rw, u64 reg_addr, - void *packed_buf, size_t size_bytes); -int sja1105_spi_send_int(const struct sja1105_private *priv, - sja1105_spi_rw_mode_t rw, u64 reg_addr, - u64 *value, u64 size_bytes); -int sja1105_spi_send_long_packed_buf(const struct sja1105_private *priv, - sja1105_spi_rw_mode_t rw, u64 base_addr, - void *packed_buf, u64 buf_len); +int sja1105_xfer_buf(const struct sja1105_private *priv, + sja1105_spi_rw_mode_t rw, u64 reg_addr, + void *packed_buf, size_t size_bytes); +int sja1105_xfer_u32(const struct sja1105_private *priv, + sja1105_spi_rw_mode_t rw, u64 reg_addr, u32 *value); +int sja1105_xfer_u64(const struct sja1105_private *priv, + sja1105_spi_rw_mode_t rw, u64 reg_addr, u64 *value); int sja1105_static_config_upload(struct sja1105_private *priv); int sja1105_inhibit_tx(const struct sja1105_private *priv, unsigned long port_bitmap, bool tx_inhibited); diff --git a/drivers/net/dsa/sja1105/sja1105_clocking.c b/drivers/net/dsa/sja1105/sja1105_clocking.c index 608126a15d72..9082e52b55e9 100644 --- a/drivers/net/dsa/sja1105/sja1105_clocking.c +++ b/drivers/net/dsa/sja1105/sja1105_clocking.c @@ -118,9 +118,8 @@ static int sja1105_cgu_idiv_config(struct sja1105_private *priv, int port, idiv.pd = enabled ? 0 : 1; /* Power down? */ sja1105_cgu_idiv_packing(packed_buf, &idiv, PACK); - return sja1105_spi_send_packed_buf(priv, SPI_WRITE, - regs->cgu_idiv[port], packed_buf, - SJA1105_SIZE_CGU_CMD); + return sja1105_xfer_buf(priv, SPI_WRITE, regs->cgu_idiv[port], + packed_buf, SJA1105_SIZE_CGU_CMD); } static void @@ -167,9 +166,8 @@ static int sja1105_cgu_mii_tx_clk_config(struct sja1105_private *priv, mii_tx_clk.pd = 0; /* Power Down off => enabled */ sja1105_cgu_mii_control_packing(packed_buf, &mii_tx_clk, PACK); - return sja1105_spi_send_packed_buf(priv, SPI_WRITE, - regs->mii_tx_clk[port], packed_buf, - SJA1105_SIZE_CGU_CMD); + return sja1105_xfer_buf(priv, SPI_WRITE, regs->mii_tx_clk[port], + packed_buf, SJA1105_SIZE_CGU_CMD); } static int @@ -192,9 +190,8 @@ sja1105_cgu_mii_rx_clk_config(struct sja1105_private *priv, int port) mii_rx_clk.pd = 0; /* Power Down off => enabled */ sja1105_cgu_mii_control_packing(packed_buf, &mii_rx_clk, PACK); - return sja1105_spi_send_packed_buf(priv, SPI_WRITE, - regs->mii_rx_clk[port], packed_buf, - SJA1105_SIZE_CGU_CMD); + return sja1105_xfer_buf(priv, SPI_WRITE, regs->mii_rx_clk[port], + packed_buf, SJA1105_SIZE_CGU_CMD); } static int @@ -217,9 +214,8 @@ sja1105_cgu_mii_ext_tx_clk_config(struct sja1105_private *priv, int port) mii_ext_tx_clk.pd = 0; /* Power Down off => enabled */ sja1105_cgu_mii_control_packing(packed_buf, &mii_ext_tx_clk, PACK); - return sja1105_spi_send_packed_buf(priv, SPI_WRITE, - regs->mii_ext_tx_clk[port], - packed_buf, SJA1105_SIZE_CGU_CMD); + return sja1105_xfer_buf(priv, SPI_WRITE, regs->mii_ext_tx_clk[port], + packed_buf, SJA1105_SIZE_CGU_CMD); } static int @@ -242,9 +238,8 @@ sja1105_cgu_mii_ext_rx_clk_config(struct sja1105_private *priv, int port) mii_ext_rx_clk.pd = 0; /* Power Down off => enabled */ sja1105_cgu_mii_control_packing(packed_buf, &mii_ext_rx_clk, PACK); - return sja1105_spi_send_packed_buf(priv, SPI_WRITE, - regs->mii_ext_rx_clk[port], - packed_buf, SJA1105_SIZE_CGU_CMD); + return sja1105_xfer_buf(priv, SPI_WRITE, regs->mii_ext_rx_clk[port], + packed_buf, SJA1105_SIZE_CGU_CMD); } static int sja1105_mii_clocking_setup(struct sja1105_private *priv, int port, @@ -337,9 +332,8 @@ static int sja1105_cgu_rgmii_tx_clk_config(struct sja1105_private *priv, txc.pd = 0; sja1105_cgu_mii_control_packing(packed_buf, &txc, PACK); - return sja1105_spi_send_packed_buf(priv, SPI_WRITE, - regs->rgmii_tx_clk[port], - packed_buf, SJA1105_SIZE_CGU_CMD); + return sja1105_xfer_buf(priv, SPI_WRITE, regs->rgmii_tx_clk[port], + packed_buf, SJA1105_SIZE_CGU_CMD); } /* AGU */ @@ -383,9 +377,8 @@ static int sja1105_rgmii_cfg_pad_tx_config(struct sja1105_private *priv, pad_mii_tx.clk_ipud = 2; /* TX_CLK input stage (default) */ sja1105_cfg_pad_mii_tx_packing(packed_buf, &pad_mii_tx, PACK); - return sja1105_spi_send_packed_buf(priv, SPI_WRITE, - regs->pad_mii_tx[port], - packed_buf, SJA1105_SIZE_CGU_CMD); + return sja1105_xfer_buf(priv, SPI_WRITE, regs->pad_mii_tx[port], + packed_buf, SJA1105_SIZE_CGU_CMD); } static void @@ -405,7 +398,7 @@ sja1105_cfg_pad_mii_id_packing(void *buf, struct sja1105_cfg_pad_mii_id *cmd, } /* Valid range in degrees is an integer between 73.8 and 101.7 */ -static inline u64 sja1105_rgmii_delay(u64 phase) +static u64 sja1105_rgmii_delay(u64 phase) { /* UM11040.pdf: The delay in degree phase is 73.8 + delay_tune * 0.9. * To avoid floating point operations we'll multiply by 10 @@ -442,9 +435,8 @@ int sja1105pqrs_setup_rgmii_delay(const void *ctx, int port) pad_mii_id.txc_pd = 1; sja1105_cfg_pad_mii_id_packing(packed_buf, &pad_mii_id, PACK); - rc = sja1105_spi_send_packed_buf(priv, SPI_WRITE, - regs->pad_mii_id[port], - packed_buf, SJA1105_SIZE_CGU_CMD); + rc = sja1105_xfer_buf(priv, SPI_WRITE, regs->pad_mii_id[port], + packed_buf, SJA1105_SIZE_CGU_CMD); if (rc < 0) return rc; @@ -459,9 +451,8 @@ int sja1105pqrs_setup_rgmii_delay(const void *ctx, int port) } sja1105_cfg_pad_mii_id_packing(packed_buf, &pad_mii_id, PACK); - return sja1105_spi_send_packed_buf(priv, SPI_WRITE, - regs->pad_mii_id[port], - packed_buf, SJA1105_SIZE_CGU_CMD); + 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, @@ -547,9 +538,8 @@ static int sja1105_cgu_rmii_ref_clk_config(struct sja1105_private *priv, ref_clk.pd = 0; /* Power Down off => enabled */ sja1105_cgu_mii_control_packing(packed_buf, &ref_clk, PACK); - return sja1105_spi_send_packed_buf(priv, SPI_WRITE, - regs->rmii_ref_clk[port], - packed_buf, SJA1105_SIZE_CGU_CMD); + return sja1105_xfer_buf(priv, SPI_WRITE, regs->rmii_ref_clk[port], + packed_buf, SJA1105_SIZE_CGU_CMD); } static int @@ -565,9 +555,8 @@ sja1105_cgu_rmii_ext_tx_clk_config(struct sja1105_private *priv, int port) ext_tx_clk.pd = 0; /* Power Down off => enabled */ sja1105_cgu_mii_control_packing(packed_buf, &ext_tx_clk, PACK); - return sja1105_spi_send_packed_buf(priv, SPI_WRITE, - regs->rmii_ext_tx_clk[port], - packed_buf, SJA1105_SIZE_CGU_CMD); + return sja1105_xfer_buf(priv, SPI_WRITE, regs->rmii_ext_tx_clk[port], + packed_buf, SJA1105_SIZE_CGU_CMD); } static int sja1105_cgu_rmii_pll_config(struct sja1105_private *priv) @@ -595,8 +584,8 @@ static int sja1105_cgu_rmii_pll_config(struct sja1105_private *priv) pll.pd = 0x1; sja1105_cgu_pll_control_packing(packed_buf, &pll, PACK); - rc = sja1105_spi_send_packed_buf(priv, SPI_WRITE, regs->rmii_pll1, - packed_buf, SJA1105_SIZE_CGU_CMD); + rc = sja1105_xfer_buf(priv, SPI_WRITE, regs->rmii_pll1, packed_buf, + SJA1105_SIZE_CGU_CMD); if (rc < 0) { dev_err(dev, "failed to configure PLL1 for 50MHz\n"); return rc; @@ -606,8 +595,8 @@ static int sja1105_cgu_rmii_pll_config(struct sja1105_private *priv) pll.pd = 0x0; sja1105_cgu_pll_control_packing(packed_buf, &pll, PACK); - rc = sja1105_spi_send_packed_buf(priv, SPI_WRITE, regs->rmii_pll1, - packed_buf, SJA1105_SIZE_CGU_CMD); + rc = sja1105_xfer_buf(priv, SPI_WRITE, regs->rmii_pll1, packed_buf, + SJA1105_SIZE_CGU_CMD); if (rc < 0) { dev_err(dev, "failed to enable PLL1\n"); return rc; diff --git a/drivers/net/dsa/sja1105/sja1105_dynamic_config.c b/drivers/net/dsa/sja1105/sja1105_dynamic_config.c index 91da430045ff..25381bd65ed7 100644 --- a/drivers/net/dsa/sja1105/sja1105_dynamic_config.c +++ b/drivers/net/dsa/sja1105/sja1105_dynamic_config.c @@ -686,8 +686,8 @@ int sja1105_dynamic_config_read(struct sja1105_private *priv, ops->entry_packing(packed_buf, entry, PACK); /* Send SPI write operation: read config table entry */ - rc = sja1105_spi_send_packed_buf(priv, SPI_WRITE, ops->addr, - packed_buf, ops->packed_size); + rc = sja1105_xfer_buf(priv, SPI_WRITE, ops->addr, packed_buf, + ops->packed_size); if (rc < 0) return rc; @@ -698,8 +698,8 @@ int sja1105_dynamic_config_read(struct sja1105_private *priv, memset(packed_buf, 0, ops->packed_size); /* Retrieve the read operation's result */ - rc = sja1105_spi_send_packed_buf(priv, SPI_READ, ops->addr, - packed_buf, ops->packed_size); + rc = sja1105_xfer_buf(priv, SPI_READ, ops->addr, packed_buf, + ops->packed_size); if (rc < 0) return rc; @@ -771,8 +771,8 @@ int sja1105_dynamic_config_write(struct sja1105_private *priv, ops->entry_packing(packed_buf, entry, PACK); /* Send SPI write operation: read config table entry */ - rc = sja1105_spi_send_packed_buf(priv, SPI_WRITE, ops->addr, - packed_buf, ops->packed_size); + rc = sja1105_xfer_buf(priv, SPI_WRITE, ops->addr, packed_buf, + ops->packed_size); if (rc < 0) return rc; diff --git a/drivers/net/dsa/sja1105/sja1105_ethtool.c b/drivers/net/dsa/sja1105/sja1105_ethtool.c index ab581a28cd41..064301cc7d5b 100644 --- a/drivers/net/dsa/sja1105/sja1105_ethtool.c +++ b/drivers/net/dsa/sja1105/sja1105_ethtool.c @@ -167,8 +167,8 @@ static int sja1105_port_status_get_mac(struct sja1105_private *priv, int rc; /* MAC area */ - rc = sja1105_spi_send_packed_buf(priv, SPI_READ, regs->mac[port], - packed_buf, SJA1105_SIZE_MAC_AREA); + rc = sja1105_xfer_buf(priv, SPI_READ, regs->mac[port], packed_buf, + SJA1105_SIZE_MAC_AREA); if (rc < 0) return rc; @@ -185,8 +185,8 @@ static int sja1105_port_status_get_hl1(struct sja1105_private *priv, u8 packed_buf[SJA1105_SIZE_HL1_AREA] = {0}; int rc; - rc = sja1105_spi_send_packed_buf(priv, SPI_READ, regs->mac_hl1[port], - packed_buf, SJA1105_SIZE_HL1_AREA); + rc = sja1105_xfer_buf(priv, SPI_READ, regs->mac_hl1[port], packed_buf, + SJA1105_SIZE_HL1_AREA); if (rc < 0) return rc; @@ -203,8 +203,8 @@ static int sja1105_port_status_get_hl2(struct sja1105_private *priv, u8 packed_buf[SJA1105_SIZE_QLEVEL_AREA] = {0}; int rc; - rc = sja1105_spi_send_packed_buf(priv, SPI_READ, regs->mac_hl2[port], - packed_buf, SJA1105_SIZE_HL2_AREA); + rc = sja1105_xfer_buf(priv, SPI_READ, regs->mac_hl2[port], packed_buf, + SJA1105_SIZE_HL2_AREA); if (rc < 0) return rc; @@ -215,8 +215,8 @@ static int sja1105_port_status_get_hl2(struct sja1105_private *priv, priv->info->device_id == SJA1105T_DEVICE_ID) return 0; - rc = sja1105_spi_send_packed_buf(priv, SPI_READ, regs->qlevel[port], - packed_buf, SJA1105_SIZE_QLEVEL_AREA); + rc = sja1105_xfer_buf(priv, SPI_READ, regs->qlevel[port], packed_buf, + SJA1105_SIZE_QLEVEL_AREA); if (rc < 0) return rc; diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index 7687ddcae159..6ce46d7e971a 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -382,8 +382,8 @@ static int sja1105_init_l2_forwarding_params(struct sja1105_private *priv) static int sja1105_init_general_params(struct sja1105_private *priv) { struct sja1105_general_params_entry default_general_params = { - /* Disallow dynamic changing of the mirror port */ - .mirr_ptacu = 0, + /* Allow dynamic changing of the mirror port */ + .mirr_ptacu = true, .switchid = priv->ds->index, /* Priority queue for link-local management frames * (both ingress to and egress from CPU - PTP, STP etc) @@ -403,8 +403,8 @@ static int sja1105_init_general_params(struct sja1105_private *priv) * by installing a temporary 'management route' */ .host_port = dsa_upstream_port(priv->ds, 0), - /* Same as host port */ - .mirr_port = dsa_upstream_port(priv->ds, 0), + /* Default to an invalid value */ + .mirr_port = SJA1105_NUM_PORTS, /* Link-local traffic received on casc_port will be forwarded * to host_port without embedding the source port and device ID * info in the destination MAC address (presumably because it @@ -458,9 +458,8 @@ static int sja1105_init_general_params(struct sja1105_private *priv) #define SJA1105_RATE_MBPS(speed) (((speed) * 64000) / 1000) -static inline void -sja1105_setup_policer(struct sja1105_l2_policing_entry *policing, - int index) +static void sja1105_setup_policer(struct sja1105_l2_policing_entry *policing, + int index) { policing[index].sharindx = index; policing[index].smax = 65535; /* Burst size in bytes */ @@ -951,7 +950,7 @@ sja1105_static_fdb_change(struct sja1105_private *priv, int port, * For the placement of a newly learnt FDB entry, the switch selects the bin * based on a hash function, and the way within that bin incrementally. */ -static inline int sja1105et_fdb_index(int bin, int way) +static int sja1105et_fdb_index(int bin, int way) { return bin * SJA1105ET_FDB_BIN_SIZE + way; } @@ -2073,6 +2072,84 @@ static int sja1105_port_setup_tc(struct dsa_switch *ds, int port, } } +/* We have a single mirror (@to) port, but can configure ingress and egress + * mirroring on all other (@from) ports. + * We need to allow mirroring rules only as long as the @to port is always the + * same, and we need to unset the @to port from mirr_port only when there is no + * mirroring rule that references it. + */ +static int sja1105_mirror_apply(struct sja1105_private *priv, int from, int to, + bool ingress, bool enabled) +{ + struct sja1105_general_params_entry *general_params; + struct sja1105_mac_config_entry *mac; + struct sja1105_table *table; + bool already_enabled; + u64 new_mirr_port; + int rc; + + table = &priv->static_config.tables[BLK_IDX_GENERAL_PARAMS]; + general_params = table->entries; + + mac = priv->static_config.tables[BLK_IDX_MAC_CONFIG].entries; + + already_enabled = (general_params->mirr_port != SJA1105_NUM_PORTS); + if (already_enabled && enabled && general_params->mirr_port != to) { + dev_err(priv->ds->dev, + "Delete mirroring rules towards port %llu first\n", + general_params->mirr_port); + return -EBUSY; + } + + new_mirr_port = to; + if (!enabled) { + bool keep = false; + int port; + + /* Anybody still referencing mirr_port? */ + for (port = 0; port < SJA1105_NUM_PORTS; port++) { + if (mac[port].ing_mirr || mac[port].egr_mirr) { + keep = true; + break; + } + } + /* Unset already_enabled for next time */ + if (!keep) + new_mirr_port = SJA1105_NUM_PORTS; + } + if (new_mirr_port != general_params->mirr_port) { + general_params->mirr_port = new_mirr_port; + + rc = sja1105_dynamic_config_write(priv, BLK_IDX_GENERAL_PARAMS, + 0, general_params, true); + if (rc < 0) + return rc; + } + + if (ingress) + mac[from].ing_mirr = enabled; + else + mac[from].egr_mirr = enabled; + + return sja1105_dynamic_config_write(priv, BLK_IDX_MAC_CONFIG, from, + &mac[from], true); +} + +static int sja1105_mirror_add(struct dsa_switch *ds, int port, + struct dsa_mall_mirror_tc_entry *mirror, + bool ingress) +{ + return sja1105_mirror_apply(ds->priv, port, mirror->to_local_port, + ingress, true); +} + +static void sja1105_mirror_del(struct dsa_switch *ds, int port, + struct dsa_mall_mirror_tc_entry *mirror) +{ + sja1105_mirror_apply(ds->priv, port, mirror->to_local_port, + mirror->ingress, false); +} + static const struct dsa_switch_ops sja1105_switch_ops = { .get_tag_protocol = sja1105_get_tag_protocol, .setup = sja1105_setup, @@ -2106,6 +2183,8 @@ static const struct dsa_switch_ops sja1105_switch_ops = { .port_rxtstamp = sja1105_port_rxtstamp, .port_txtstamp = sja1105_port_txtstamp, .port_setup_tc = sja1105_port_setup_tc, + .port_mirror_add = sja1105_mirror_add, + .port_mirror_del = sja1105_mirror_del, }; static int sja1105_check_device_id(struct sja1105_private *priv) @@ -2113,23 +2192,22 @@ static int sja1105_check_device_id(struct sja1105_private *priv) const struct sja1105_regs *regs = priv->info->regs; u8 prod_id[SJA1105_SIZE_DEVICE_ID] = {0}; struct device *dev = &priv->spidev->dev; - u64 device_id; + u32 device_id; u64 part_no; int rc; - rc = sja1105_spi_send_int(priv, SPI_READ, regs->device_id, - &device_id, SJA1105_SIZE_DEVICE_ID); + rc = sja1105_xfer_u32(priv, SPI_READ, regs->device_id, &device_id); if (rc < 0) return rc; if (device_id != priv->info->device_id) { - dev_err(dev, "Expected device ID 0x%llx but read 0x%llx\n", + dev_err(dev, "Expected device ID 0x%llx but read 0x%x\n", priv->info->device_id, device_id); return -ENODEV; } - rc = sja1105_spi_send_packed_buf(priv, SPI_READ, regs->prod_id, - prod_id, SJA1105_SIZE_DEVICE_ID); + rc = sja1105_xfer_buf(priv, SPI_READ, regs->prod_id, prod_id, + SJA1105_SIZE_DEVICE_ID); if (rc < 0) return rc; diff --git a/drivers/net/dsa/sja1105/sja1105_ptp.c b/drivers/net/dsa/sja1105/sja1105_ptp.c index d8e8dd59f3d1..0df1bbec475a 100644 --- a/drivers/net/dsa/sja1105/sja1105_ptp.c +++ b/drivers/net/dsa/sja1105/sja1105_ptp.c @@ -91,8 +91,8 @@ int sja1105et_ptp_cmd(const void *ctx, const void *data) sja1105_pack(buf, &valid, 31, 31, size); sja1105_pack(buf, &cmd->resptp, 2, 2, size); - return sja1105_spi_send_packed_buf(priv, SPI_WRITE, regs->ptp_control, - buf, SJA1105_SIZE_PTP_CMD); + return sja1105_xfer_buf(priv, SPI_WRITE, regs->ptp_control, buf, + SJA1105_SIZE_PTP_CMD); } int sja1105pqrs_ptp_cmd(const void *ctx, const void *data) @@ -108,8 +108,8 @@ int sja1105pqrs_ptp_cmd(const void *ctx, const void *data) sja1105_pack(buf, &valid, 31, 31, size); sja1105_pack(buf, &cmd->resptp, 3, 3, size); - return sja1105_spi_send_packed_buf(priv, SPI_WRITE, regs->ptp_control, - buf, SJA1105_SIZE_PTP_CMD); + return sja1105_xfer_buf(priv, SPI_WRITE, regs->ptp_control, buf, + SJA1105_SIZE_PTP_CMD); } /* The switch returns partial timestamps (24 bits for SJA1105 E/T, which wrap @@ -180,10 +180,8 @@ int sja1105_ptpegr_ts_poll(struct sja1105_private *priv, int port, u64 *ts) int rc; do { - rc = sja1105_spi_send_packed_buf(priv, SPI_READ, - regs->ptpegr_ts[port], - packed_buf, - priv->info->ptpegr_ts_bytes); + rc = sja1105_xfer_buf(priv, SPI_READ, regs->ptpegr_ts[port], + packed_buf, priv->info->ptpegr_ts_bytes); if (rc < 0) return rc; @@ -327,8 +325,7 @@ static u64 sja1105_ptptsclk_read(const struct cyclecounter *cc) u64 ptptsclk = 0; int rc; - rc = sja1105_spi_send_int(priv, SPI_READ, regs->ptptsclk, - &ptptsclk, 8); + rc = sja1105_xfer_u64(priv, SPI_READ, regs->ptptsclk, &ptptsclk); if (rc < 0) dev_err_ratelimited(priv->ds->dev, "failed to read ptp cycle counter: %d\n", diff --git a/drivers/net/dsa/sja1105/sja1105_spi.c b/drivers/net/dsa/sja1105/sja1105_spi.c index 58dd37ecde17..b224b1a55695 100644 --- a/drivers/net/dsa/sja1105/sja1105_spi.c +++ b/drivers/net/dsa/sja1105/sja1105_spi.c @@ -7,7 +7,6 @@ #include <linux/packing.h> #include "sja1105.h" -#define SJA1105_SIZE_PORT_CTRL 4 #define SJA1105_SIZE_RESET_CMD 4 #define SJA1105_SIZE_SPI_MSG_HEADER 4 #define SJA1105_SIZE_SPI_MSG_MAXLEN (64 * 4) @@ -64,11 +63,11 @@ sja1105_spi_message_pack(void *buf, const struct sja1105_spi_message *msg) * * This function should only be called if it is priorly known that * @size_bytes is smaller than SIZE_SPI_MSG_MAXLEN. Larger packed buffers - * are chunked in smaller pieces by sja1105_spi_send_long_packed_buf below. + * are chunked in smaller pieces by sja1105_xfer_long_buf below. */ -int sja1105_spi_send_packed_buf(const struct sja1105_private *priv, - sja1105_spi_rw_mode_t rw, u64 reg_addr, - void *packed_buf, size_t size_bytes) +int sja1105_xfer_buf(const struct sja1105_private *priv, + sja1105_spi_rw_mode_t rw, u64 reg_addr, + void *packed_buf, size_t size_bytes) { u8 tx_buf[SJA1105_SIZE_SPI_TRANSFER_MAX] = {0}; u8 rx_buf[SJA1105_SIZE_SPI_TRANSFER_MAX] = {0}; @@ -103,35 +102,52 @@ int sja1105_spi_send_packed_buf(const struct sja1105_private *priv, /* If @rw is: * - SPI_WRITE: creates and sends an SPI write message at absolute - * address reg_addr, taking size_bytes from *packed_buf + * address reg_addr * - SPI_READ: creates and sends an SPI read message from absolute - * address reg_addr, writing size_bytes into *packed_buf + * address reg_addr * * The u64 *value is unpacked, meaning that it's stored in the native * CPU endianness and directly usable by software running on the core. - * - * This is a wrapper around sja1105_spi_send_packed_buf(). */ -int sja1105_spi_send_int(const struct sja1105_private *priv, - sja1105_spi_rw_mode_t rw, u64 reg_addr, - u64 *value, u64 size_bytes) +int sja1105_xfer_u64(const struct sja1105_private *priv, + sja1105_spi_rw_mode_t rw, u64 reg_addr, u64 *value) { - u8 packed_buf[SJA1105_SIZE_SPI_MSG_MAXLEN]; + u8 packed_buf[8]; int rc; - if (size_bytes > SJA1105_SIZE_SPI_MSG_MAXLEN) - return -ERANGE; - if (rw == SPI_WRITE) - sja1105_pack(packed_buf, value, 8 * size_bytes - 1, 0, - size_bytes); + sja1105_pack(packed_buf, value, 63, 0, 8); - rc = sja1105_spi_send_packed_buf(priv, rw, reg_addr, packed_buf, - size_bytes); + rc = sja1105_xfer_buf(priv, rw, reg_addr, packed_buf, 8); if (rw == SPI_READ) - sja1105_unpack(packed_buf, value, 8 * size_bytes - 1, 0, - size_bytes); + sja1105_unpack(packed_buf, value, 63, 0, 8); + + return rc; +} + +/* Same as above, but transfers only a 4 byte word */ +int sja1105_xfer_u32(const struct sja1105_private *priv, + sja1105_spi_rw_mode_t rw, u64 reg_addr, u32 *value) +{ + u8 packed_buf[4]; + u64 tmp; + int rc; + + if (rw == SPI_WRITE) { + /* The packing API only supports u64 as CPU word size, + * so we need to convert. + */ + tmp = *value; + sja1105_pack(packed_buf, &tmp, 31, 0, 4); + } + + rc = sja1105_xfer_buf(priv, rw, reg_addr, packed_buf, 4); + + if (rw == SPI_READ) { + sja1105_unpack(packed_buf, &tmp, 31, 0, 4); + *value = tmp; + } return rc; } @@ -140,9 +156,9 @@ int sja1105_spi_send_int(const struct sja1105_private *priv, * must be sent/received. Splitting the buffer into chunks and assembling * those into SPI messages is done automatically by this function. */ -int sja1105_spi_send_long_packed_buf(const struct sja1105_private *priv, - sja1105_spi_rw_mode_t rw, u64 base_addr, - void *packed_buf, u64 buf_len) +static int sja1105_xfer_long_buf(const struct sja1105_private *priv, + sja1105_spi_rw_mode_t rw, u64 base_addr, + void *packed_buf, u64 buf_len) { struct chunk { void *buf_ptr; @@ -158,8 +174,8 @@ int sja1105_spi_send_long_packed_buf(const struct sja1105_private *priv, chunk.len = min_t(int, buf_len, SJA1105_SIZE_SPI_MSG_MAXLEN); while (chunk.len) { - rc = sja1105_spi_send_packed_buf(priv, rw, chunk.spi_address, - chunk.buf_ptr, chunk.len); + rc = sja1105_xfer_buf(priv, rw, chunk.spi_address, + chunk.buf_ptr, chunk.len); if (rc < 0) return rc; @@ -241,8 +257,8 @@ static int sja1105et_reset_cmd(const void *ctx, const void *data) sja1105et_reset_cmd_pack(packed_buf, reset); - return sja1105_spi_send_packed_buf(priv, SPI_WRITE, regs->rgu, - packed_buf, SJA1105_SIZE_RESET_CMD); + return sja1105_xfer_buf(priv, SPI_WRITE, regs->rgu, packed_buf, + SJA1105_SIZE_RESET_CMD); } static int sja1105pqrs_reset_cmd(const void *ctx, const void *data) @@ -271,8 +287,8 @@ static int sja1105pqrs_reset_cmd(const void *ctx, const void *data) sja1105pqrs_reset_cmd_pack(packed_buf, reset); - return sja1105_spi_send_packed_buf(priv, SPI_WRITE, regs->rgu, - packed_buf, SJA1105_SIZE_RESET_CMD); + return sja1105_xfer_buf(priv, SPI_WRITE, regs->rgu, packed_buf, + SJA1105_SIZE_RESET_CMD); } static int sja1105_cold_reset(const struct sja1105_private *priv) @@ -287,11 +303,11 @@ int sja1105_inhibit_tx(const struct sja1105_private *priv, unsigned long port_bitmap, bool tx_inhibited) { const struct sja1105_regs *regs = priv->info->regs; - u64 inhibit_cmd; + u32 inhibit_cmd; int rc; - rc = sja1105_spi_send_int(priv, SPI_READ, regs->port_control, - &inhibit_cmd, SJA1105_SIZE_PORT_CTRL); + rc = sja1105_xfer_u32(priv, SPI_READ, regs->port_control, + &inhibit_cmd); if (rc < 0) return rc; @@ -300,8 +316,8 @@ int sja1105_inhibit_tx(const struct sja1105_private *priv, else inhibit_cmd &= ~port_bitmap; - return sja1105_spi_send_int(priv, SPI_WRITE, regs->port_control, - &inhibit_cmd, SJA1105_SIZE_PORT_CTRL); + return sja1105_xfer_u32(priv, SPI_WRITE, regs->port_control, + &inhibit_cmd); } struct sja1105_status { @@ -339,9 +355,7 @@ static int sja1105_status_get(struct sja1105_private *priv, u8 packed_buf[4]; int rc; - rc = sja1105_spi_send_packed_buf(priv, SPI_READ, - regs->status, - packed_buf, 4); + rc = sja1105_xfer_buf(priv, SPI_READ, regs->status, packed_buf, 4); if (rc < 0) return rc; @@ -437,9 +451,8 @@ int sja1105_static_config_upload(struct sja1105_private *priv) /* Wait for the switch to come out of reset */ usleep_range(1000, 5000); /* Upload the static config to the device */ - rc = sja1105_spi_send_long_packed_buf(priv, SPI_WRITE, - regs->config, - config_buf, buf_len); + rc = sja1105_xfer_long_buf(priv, SPI_WRITE, regs->config, + config_buf, buf_len); if (rc < 0) { dev_err(dev, "Failed to upload config, retrying...\n"); continue; |