162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/* Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com>
362306a36Sopenharmony_ci */
462306a36Sopenharmony_ci#include "sja1105.h"
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci/* In the dynamic configuration interface, the switch exposes a register-like
762306a36Sopenharmony_ci * view of some of the static configuration tables.
862306a36Sopenharmony_ci * Many times the field organization of the dynamic tables is abbreviated (not
962306a36Sopenharmony_ci * all fields are dynamically reconfigurable) and different from the static
1062306a36Sopenharmony_ci * ones, but the key reason for having it is that we can spare a switch reset
1162306a36Sopenharmony_ci * for settings that can be changed dynamically.
1262306a36Sopenharmony_ci *
1362306a36Sopenharmony_ci * This file creates a per-switch-family abstraction called
1462306a36Sopenharmony_ci * struct sja1105_dynamic_table_ops and two operations that work with it:
1562306a36Sopenharmony_ci * - sja1105_dynamic_config_write
1662306a36Sopenharmony_ci * - sja1105_dynamic_config_read
1762306a36Sopenharmony_ci *
1862306a36Sopenharmony_ci * Compared to the struct sja1105_table_ops from sja1105_static_config.c,
1962306a36Sopenharmony_ci * the dynamic accessors work with a compound buffer:
2062306a36Sopenharmony_ci *
2162306a36Sopenharmony_ci * packed_buf
2262306a36Sopenharmony_ci *
2362306a36Sopenharmony_ci * |
2462306a36Sopenharmony_ci * V
2562306a36Sopenharmony_ci * +-----------------------------------------+------------------+
2662306a36Sopenharmony_ci * |              ENTRY BUFFER               |  COMMAND BUFFER  |
2762306a36Sopenharmony_ci * +-----------------------------------------+------------------+
2862306a36Sopenharmony_ci *
2962306a36Sopenharmony_ci * <----------------------- packed_size ------------------------>
3062306a36Sopenharmony_ci *
3162306a36Sopenharmony_ci * The ENTRY BUFFER may or may not have the same layout, or size, as its static
3262306a36Sopenharmony_ci * configuration table entry counterpart. When it does, the same packing
3362306a36Sopenharmony_ci * function is reused (bar exceptional cases - see
3462306a36Sopenharmony_ci * sja1105pqrs_dyn_l2_lookup_entry_packing).
3562306a36Sopenharmony_ci *
3662306a36Sopenharmony_ci * The reason for the COMMAND BUFFER being at the end is to be able to send
3762306a36Sopenharmony_ci * a dynamic write command through a single SPI burst. By the time the switch
3862306a36Sopenharmony_ci * reacts to the command, the ENTRY BUFFER is already populated with the data
3962306a36Sopenharmony_ci * sent by the core.
4062306a36Sopenharmony_ci *
4162306a36Sopenharmony_ci * The COMMAND BUFFER is always SJA1105_SIZE_DYN_CMD bytes (one 32-bit word) in
4262306a36Sopenharmony_ci * size.
4362306a36Sopenharmony_ci *
4462306a36Sopenharmony_ci * Sometimes the ENTRY BUFFER does not really exist (when the number of fields
4562306a36Sopenharmony_ci * that can be reconfigured is small), then the switch repurposes some of the
4662306a36Sopenharmony_ci * unused 32 bits of the COMMAND BUFFER to hold ENTRY data.
4762306a36Sopenharmony_ci *
4862306a36Sopenharmony_ci * The key members of struct sja1105_dynamic_table_ops are:
4962306a36Sopenharmony_ci * - .entry_packing: A function that deals with packing an ENTRY structure
5062306a36Sopenharmony_ci *		     into an SPI buffer, or retrieving an ENTRY structure
5162306a36Sopenharmony_ci *		     from one.
5262306a36Sopenharmony_ci *		     The @packed_buf pointer it's given does always point to
5362306a36Sopenharmony_ci *		     the ENTRY portion of the buffer.
5462306a36Sopenharmony_ci * - .cmd_packing: A function that deals with packing/unpacking the COMMAND
5562306a36Sopenharmony_ci *		   structure to/from the SPI buffer.
5662306a36Sopenharmony_ci *		   It is given the same @packed_buf pointer as .entry_packing,
5762306a36Sopenharmony_ci *		   so most of the time, the @packed_buf points *behind* the
5862306a36Sopenharmony_ci *		   COMMAND offset inside the buffer.
5962306a36Sopenharmony_ci *		   To access the COMMAND portion of the buffer, the function
6062306a36Sopenharmony_ci *		   knows its correct offset.
6162306a36Sopenharmony_ci *		   Giving both functions the same pointer is handy because in
6262306a36Sopenharmony_ci *		   extreme cases (see sja1105pqrs_dyn_l2_lookup_entry_packing)
6362306a36Sopenharmony_ci *		   the .entry_packing is able to jump to the COMMAND portion,
6462306a36Sopenharmony_ci *		   or vice-versa (sja1105pqrs_l2_lookup_cmd_packing).
6562306a36Sopenharmony_ci * - .access: A bitmap of:
6662306a36Sopenharmony_ci *	OP_READ: Set if the hardware manual marks the ENTRY portion of the
6762306a36Sopenharmony_ci *		 dynamic configuration table buffer as R (readable) after
6862306a36Sopenharmony_ci *		 an SPI read command (the switch will populate the buffer).
6962306a36Sopenharmony_ci *	OP_WRITE: Set if the manual marks the ENTRY portion of the dynamic
7062306a36Sopenharmony_ci *		  table buffer as W (writable) after an SPI write command
7162306a36Sopenharmony_ci *		  (the switch will read the fields provided in the buffer).
7262306a36Sopenharmony_ci *	OP_DEL: Set if the manual says the VALIDENT bit is supported in the
7362306a36Sopenharmony_ci *		COMMAND portion of this dynamic config buffer (i.e. the
7462306a36Sopenharmony_ci *		specified entry can be invalidated through a SPI write
7562306a36Sopenharmony_ci *		command).
7662306a36Sopenharmony_ci *	OP_SEARCH: Set if the manual says that the index of an entry can
7762306a36Sopenharmony_ci *		   be retrieved in the COMMAND portion of the buffer based
7862306a36Sopenharmony_ci *		   on its ENTRY portion, as a result of a SPI write command.
7962306a36Sopenharmony_ci *		   Only the TCAM-based FDB table on SJA1105 P/Q/R/S supports
8062306a36Sopenharmony_ci *		   this.
8162306a36Sopenharmony_ci *	OP_VALID_ANYWAY: Reading some tables through the dynamic config
8262306a36Sopenharmony_ci *			 interface is possible even if the VALIDENT bit is not
8362306a36Sopenharmony_ci *			 set in the writeback. So don't error out in that case.
8462306a36Sopenharmony_ci * - .max_entry_count: The number of entries, counting from zero, that can be
8562306a36Sopenharmony_ci *		       reconfigured through the dynamic interface. If a static
8662306a36Sopenharmony_ci *		       table can be reconfigured at all dynamically, this
8762306a36Sopenharmony_ci *		       number always matches the maximum number of supported
8862306a36Sopenharmony_ci *		       static entries.
8962306a36Sopenharmony_ci * - .packed_size: The length in bytes of the compound ENTRY + COMMAND BUFFER.
9062306a36Sopenharmony_ci *		   Note that sometimes the compound buffer may contain holes in
9162306a36Sopenharmony_ci *		   it (see sja1105_vlan_lookup_cmd_packing). The @packed_buf is
9262306a36Sopenharmony_ci *		   contiguous however, so @packed_size includes any unused
9362306a36Sopenharmony_ci *		   bytes.
9462306a36Sopenharmony_ci * - .addr: The base SPI address at which the buffer must be written to the
9562306a36Sopenharmony_ci *	    switch's memory. When looking at the hardware manual, this must
9662306a36Sopenharmony_ci *	    always match the lowest documented address for the ENTRY, and not
9762306a36Sopenharmony_ci *	    that of the COMMAND, since the other 32-bit words will follow along
9862306a36Sopenharmony_ci *	    at the correct addresses.
9962306a36Sopenharmony_ci */
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci#define SJA1105_SIZE_DYN_CMD					4
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci#define SJA1105ET_SIZE_VL_LOOKUP_DYN_CMD			\
10462306a36Sopenharmony_ci	SJA1105_SIZE_DYN_CMD
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci#define SJA1105PQRS_SIZE_VL_LOOKUP_DYN_CMD			\
10762306a36Sopenharmony_ci	(SJA1105_SIZE_DYN_CMD + SJA1105_SIZE_VL_LOOKUP_ENTRY)
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci#define SJA1110_SIZE_VL_POLICING_DYN_CMD			\
11062306a36Sopenharmony_ci	(SJA1105_SIZE_DYN_CMD + SJA1105_SIZE_VL_POLICING_ENTRY)
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci#define SJA1105ET_SIZE_MAC_CONFIG_DYN_ENTRY			\
11362306a36Sopenharmony_ci	SJA1105_SIZE_DYN_CMD
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci#define SJA1105ET_SIZE_L2_LOOKUP_DYN_CMD			\
11662306a36Sopenharmony_ci	(SJA1105_SIZE_DYN_CMD + SJA1105ET_SIZE_L2_LOOKUP_ENTRY)
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci#define SJA1105PQRS_SIZE_L2_LOOKUP_DYN_CMD			\
11962306a36Sopenharmony_ci	(SJA1105_SIZE_DYN_CMD + SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY)
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci#define SJA1110_SIZE_L2_LOOKUP_DYN_CMD				\
12262306a36Sopenharmony_ci	(SJA1105_SIZE_DYN_CMD + SJA1110_SIZE_L2_LOOKUP_ENTRY)
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci#define SJA1105_SIZE_VLAN_LOOKUP_DYN_CMD			\
12562306a36Sopenharmony_ci	(SJA1105_SIZE_DYN_CMD + 4 + SJA1105_SIZE_VLAN_LOOKUP_ENTRY)
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci#define SJA1110_SIZE_VLAN_LOOKUP_DYN_CMD			\
12862306a36Sopenharmony_ci	(SJA1105_SIZE_DYN_CMD + SJA1110_SIZE_VLAN_LOOKUP_ENTRY)
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci#define SJA1105_SIZE_L2_FORWARDING_DYN_CMD			\
13162306a36Sopenharmony_ci	(SJA1105_SIZE_DYN_CMD + SJA1105_SIZE_L2_FORWARDING_ENTRY)
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci#define SJA1105ET_SIZE_MAC_CONFIG_DYN_CMD			\
13462306a36Sopenharmony_ci	(SJA1105_SIZE_DYN_CMD + SJA1105ET_SIZE_MAC_CONFIG_DYN_ENTRY)
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_ci#define SJA1105PQRS_SIZE_MAC_CONFIG_DYN_CMD			\
13762306a36Sopenharmony_ci	(SJA1105_SIZE_DYN_CMD + SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY)
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci#define SJA1105ET_SIZE_L2_LOOKUP_PARAMS_DYN_CMD			\
14062306a36Sopenharmony_ci	SJA1105_SIZE_DYN_CMD
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci#define SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_DYN_CMD		\
14362306a36Sopenharmony_ci	(SJA1105_SIZE_DYN_CMD + SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_ENTRY)
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci#define SJA1110_SIZE_L2_LOOKUP_PARAMS_DYN_CMD		\
14662306a36Sopenharmony_ci	(SJA1105_SIZE_DYN_CMD + SJA1110_SIZE_L2_LOOKUP_PARAMS_ENTRY)
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci#define SJA1105ET_SIZE_GENERAL_PARAMS_DYN_CMD			\
14962306a36Sopenharmony_ci	SJA1105_SIZE_DYN_CMD
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci#define SJA1105PQRS_SIZE_GENERAL_PARAMS_DYN_CMD			\
15262306a36Sopenharmony_ci	(SJA1105_SIZE_DYN_CMD + SJA1105PQRS_SIZE_GENERAL_PARAMS_ENTRY)
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci#define SJA1110_SIZE_GENERAL_PARAMS_DYN_CMD			\
15562306a36Sopenharmony_ci	(SJA1105_SIZE_DYN_CMD + SJA1110_SIZE_GENERAL_PARAMS_ENTRY)
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci#define SJA1105PQRS_SIZE_AVB_PARAMS_DYN_CMD			\
15862306a36Sopenharmony_ci	(SJA1105_SIZE_DYN_CMD + SJA1105PQRS_SIZE_AVB_PARAMS_ENTRY)
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ci#define SJA1105_SIZE_RETAGGING_DYN_CMD				\
16162306a36Sopenharmony_ci	(SJA1105_SIZE_DYN_CMD + SJA1105_SIZE_RETAGGING_ENTRY)
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ci#define SJA1105ET_SIZE_CBS_DYN_CMD				\
16462306a36Sopenharmony_ci	(SJA1105_SIZE_DYN_CMD + SJA1105ET_SIZE_CBS_ENTRY)
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ci#define SJA1105PQRS_SIZE_CBS_DYN_CMD				\
16762306a36Sopenharmony_ci	(SJA1105_SIZE_DYN_CMD + SJA1105PQRS_SIZE_CBS_ENTRY)
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ci#define SJA1110_SIZE_XMII_PARAMS_DYN_CMD			\
17062306a36Sopenharmony_ci	SJA1110_SIZE_XMII_PARAMS_ENTRY
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci#define SJA1110_SIZE_L2_POLICING_DYN_CMD			\
17362306a36Sopenharmony_ci	(SJA1105_SIZE_DYN_CMD + SJA1105_SIZE_L2_POLICING_ENTRY)
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci#define SJA1110_SIZE_L2_FORWARDING_PARAMS_DYN_CMD		\
17662306a36Sopenharmony_ci	SJA1105_SIZE_L2_FORWARDING_PARAMS_ENTRY
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ci#define SJA1105_MAX_DYN_CMD_SIZE				\
17962306a36Sopenharmony_ci	SJA1110_SIZE_GENERAL_PARAMS_DYN_CMD
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_cistruct sja1105_dyn_cmd {
18262306a36Sopenharmony_ci	bool search;
18362306a36Sopenharmony_ci	u64 valid;
18462306a36Sopenharmony_ci	u64 rdwrset;
18562306a36Sopenharmony_ci	u64 errors;
18662306a36Sopenharmony_ci	u64 valident;
18762306a36Sopenharmony_ci	u64 index;
18862306a36Sopenharmony_ci};
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_cienum sja1105_hostcmd {
19162306a36Sopenharmony_ci	SJA1105_HOSTCMD_SEARCH = 1,
19262306a36Sopenharmony_ci	SJA1105_HOSTCMD_READ = 2,
19362306a36Sopenharmony_ci	SJA1105_HOSTCMD_WRITE = 3,
19462306a36Sopenharmony_ci	SJA1105_HOSTCMD_INVALIDATE = 4,
19562306a36Sopenharmony_ci};
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ci/* Command and entry overlap */
19862306a36Sopenharmony_cistatic void
19962306a36Sopenharmony_cisja1105et_vl_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
20062306a36Sopenharmony_ci				enum packing_op op)
20162306a36Sopenharmony_ci{
20262306a36Sopenharmony_ci	const int size = SJA1105_SIZE_DYN_CMD;
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci	sja1105_packing(buf, &cmd->valid,   31, 31, size, op);
20562306a36Sopenharmony_ci	sja1105_packing(buf, &cmd->errors,  30, 30, size, op);
20662306a36Sopenharmony_ci	sja1105_packing(buf, &cmd->rdwrset, 29, 29, size, op);
20762306a36Sopenharmony_ci	sja1105_packing(buf, &cmd->index,    9,  0, size, op);
20862306a36Sopenharmony_ci}
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci/* Command and entry are separate */
21162306a36Sopenharmony_cistatic void
21262306a36Sopenharmony_cisja1105pqrs_vl_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
21362306a36Sopenharmony_ci				  enum packing_op op)
21462306a36Sopenharmony_ci{
21562306a36Sopenharmony_ci	u8 *p = buf + SJA1105_SIZE_VL_LOOKUP_ENTRY;
21662306a36Sopenharmony_ci	const int size = SJA1105_SIZE_DYN_CMD;
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci	sja1105_packing(p, &cmd->valid,   31, 31, size, op);
21962306a36Sopenharmony_ci	sja1105_packing(p, &cmd->errors,  30, 30, size, op);
22062306a36Sopenharmony_ci	sja1105_packing(p, &cmd->rdwrset, 29, 29, size, op);
22162306a36Sopenharmony_ci	sja1105_packing(p, &cmd->index,    9,  0, size, op);
22262306a36Sopenharmony_ci}
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_cistatic void
22562306a36Sopenharmony_cisja1110_vl_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
22662306a36Sopenharmony_ci			      enum packing_op op)
22762306a36Sopenharmony_ci{
22862306a36Sopenharmony_ci	u8 *p = buf + SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY;
22962306a36Sopenharmony_ci	const int size = SJA1105_SIZE_DYN_CMD;
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_ci	sja1105_packing(p, &cmd->valid,   31, 31, size, op);
23262306a36Sopenharmony_ci	sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op);
23362306a36Sopenharmony_ci	sja1105_packing(p, &cmd->errors,  29, 29, size, op);
23462306a36Sopenharmony_ci	sja1105_packing(p, &cmd->index,   11,  0, size, op);
23562306a36Sopenharmony_ci}
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_cistatic size_t sja1105et_vl_lookup_entry_packing(void *buf, void *entry_ptr,
23862306a36Sopenharmony_ci						enum packing_op op)
23962306a36Sopenharmony_ci{
24062306a36Sopenharmony_ci	struct sja1105_vl_lookup_entry *entry = entry_ptr;
24162306a36Sopenharmony_ci	const int size = SJA1105ET_SIZE_VL_LOOKUP_DYN_CMD;
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci	sja1105_packing(buf, &entry->egrmirr,  21, 17, size, op);
24462306a36Sopenharmony_ci	sja1105_packing(buf, &entry->ingrmirr, 16, 16, size, op);
24562306a36Sopenharmony_ci	return size;
24662306a36Sopenharmony_ci}
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_cistatic void
24962306a36Sopenharmony_cisja1110_vl_policing_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
25062306a36Sopenharmony_ci				enum packing_op op)
25162306a36Sopenharmony_ci{
25262306a36Sopenharmony_ci	u8 *p = buf + SJA1105_SIZE_VL_LOOKUP_ENTRY;
25362306a36Sopenharmony_ci	const int size = SJA1105_SIZE_DYN_CMD;
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci	sja1105_packing(p, &cmd->valid,   31, 31, size, op);
25662306a36Sopenharmony_ci	sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op);
25762306a36Sopenharmony_ci	sja1105_packing(p, &cmd->index,   11,  0, size, op);
25862306a36Sopenharmony_ci}
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_cistatic void
26162306a36Sopenharmony_cisja1105pqrs_common_l2_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
26262306a36Sopenharmony_ci					 enum packing_op op, int entry_size)
26362306a36Sopenharmony_ci{
26462306a36Sopenharmony_ci	const int size = SJA1105_SIZE_DYN_CMD;
26562306a36Sopenharmony_ci	u8 *p = buf + entry_size;
26662306a36Sopenharmony_ci	u64 hostcmd;
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_ci	sja1105_packing(p, &cmd->valid,    31, 31, size, op);
26962306a36Sopenharmony_ci	sja1105_packing(p, &cmd->rdwrset,  30, 30, size, op);
27062306a36Sopenharmony_ci	sja1105_packing(p, &cmd->errors,   29, 29, size, op);
27162306a36Sopenharmony_ci	sja1105_packing(p, &cmd->valident, 27, 27, size, op);
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_ci	/* VALIDENT is supposed to indicate "keep or not", but in SJA1105 E/T,
27462306a36Sopenharmony_ci	 * using it to delete a management route was unsupported. UM10944
27562306a36Sopenharmony_ci	 * said about it:
27662306a36Sopenharmony_ci	 *
27762306a36Sopenharmony_ci	 *   In case of a write access with the MGMTROUTE flag set,
27862306a36Sopenharmony_ci	 *   the flag will be ignored. It will always be found cleared
27962306a36Sopenharmony_ci	 *   for read accesses with the MGMTROUTE flag set.
28062306a36Sopenharmony_ci	 *
28162306a36Sopenharmony_ci	 * SJA1105 P/Q/R/S keeps the same behavior w.r.t. VALIDENT, but there
28262306a36Sopenharmony_ci	 * is now another flag called HOSTCMD which does more stuff (quoting
28362306a36Sopenharmony_ci	 * from UM11040):
28462306a36Sopenharmony_ci	 *
28562306a36Sopenharmony_ci	 *   A write request is accepted only when HOSTCMD is set to write host
28662306a36Sopenharmony_ci	 *   or invalid. A read request is accepted only when HOSTCMD is set to
28762306a36Sopenharmony_ci	 *   search host or read host.
28862306a36Sopenharmony_ci	 *
28962306a36Sopenharmony_ci	 * So it is possible to translate a RDWRSET/VALIDENT combination into
29062306a36Sopenharmony_ci	 * HOSTCMD so that we keep the dynamic command API in place, and
29162306a36Sopenharmony_ci	 * at the same time achieve compatibility with the management route
29262306a36Sopenharmony_ci	 * command structure.
29362306a36Sopenharmony_ci	 */
29462306a36Sopenharmony_ci	if (cmd->rdwrset == SPI_READ) {
29562306a36Sopenharmony_ci		if (cmd->search)
29662306a36Sopenharmony_ci			hostcmd = SJA1105_HOSTCMD_SEARCH;
29762306a36Sopenharmony_ci		else
29862306a36Sopenharmony_ci			hostcmd = SJA1105_HOSTCMD_READ;
29962306a36Sopenharmony_ci	} else {
30062306a36Sopenharmony_ci		/* SPI_WRITE */
30162306a36Sopenharmony_ci		if (cmd->valident)
30262306a36Sopenharmony_ci			hostcmd = SJA1105_HOSTCMD_WRITE;
30362306a36Sopenharmony_ci		else
30462306a36Sopenharmony_ci			hostcmd = SJA1105_HOSTCMD_INVALIDATE;
30562306a36Sopenharmony_ci	}
30662306a36Sopenharmony_ci	sja1105_packing(p, &hostcmd, 25, 23, size, op);
30762306a36Sopenharmony_ci}
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_cistatic void
31062306a36Sopenharmony_cisja1105pqrs_l2_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
31162306a36Sopenharmony_ci				  enum packing_op op)
31262306a36Sopenharmony_ci{
31362306a36Sopenharmony_ci	int entry_size = SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY;
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci	sja1105pqrs_common_l2_lookup_cmd_packing(buf, cmd, op, entry_size);
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_ci	/* Hack - The hardware takes the 'index' field within
31862306a36Sopenharmony_ci	 * struct sja1105_l2_lookup_entry as the index on which this command
31962306a36Sopenharmony_ci	 * will operate. However it will ignore everything else, so 'index'
32062306a36Sopenharmony_ci	 * is logically part of command but physically part of entry.
32162306a36Sopenharmony_ci	 * Populate the 'index' entry field from within the command callback,
32262306a36Sopenharmony_ci	 * such that our API doesn't need to ask for a full-blown entry
32362306a36Sopenharmony_ci	 * structure when e.g. a delete is requested.
32462306a36Sopenharmony_ci	 */
32562306a36Sopenharmony_ci	sja1105_packing(buf, &cmd->index, 15, 6, entry_size, op);
32662306a36Sopenharmony_ci}
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_cistatic void
32962306a36Sopenharmony_cisja1110_l2_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
33062306a36Sopenharmony_ci			      enum packing_op op)
33162306a36Sopenharmony_ci{
33262306a36Sopenharmony_ci	int entry_size = SJA1110_SIZE_L2_LOOKUP_ENTRY;
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci	sja1105pqrs_common_l2_lookup_cmd_packing(buf, cmd, op, entry_size);
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ci	sja1105_packing(buf, &cmd->index, 10, 1, entry_size, op);
33762306a36Sopenharmony_ci}
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_ci/* The switch is so retarded that it makes our command/entry abstraction
34062306a36Sopenharmony_ci * crumble apart.
34162306a36Sopenharmony_ci *
34262306a36Sopenharmony_ci * On P/Q/R/S, the switch tries to say whether a FDB entry
34362306a36Sopenharmony_ci * is statically programmed or dynamically learned via a flag called LOCKEDS.
34462306a36Sopenharmony_ci * The hardware manual says about this fiels:
34562306a36Sopenharmony_ci *
34662306a36Sopenharmony_ci *   On write will specify the format of ENTRY.
34762306a36Sopenharmony_ci *   On read the flag will be found cleared at times the VALID flag is found
34862306a36Sopenharmony_ci *   set.  The flag will also be found cleared in response to a read having the
34962306a36Sopenharmony_ci *   MGMTROUTE flag set.  In response to a read with the MGMTROUTE flag
35062306a36Sopenharmony_ci *   cleared, the flag be set if the most recent access operated on an entry
35162306a36Sopenharmony_ci *   that was either loaded by configuration or through dynamic reconfiguration
35262306a36Sopenharmony_ci *   (as opposed to automatically learned entries).
35362306a36Sopenharmony_ci *
35462306a36Sopenharmony_ci * The trouble with this flag is that it's part of the *command* to access the
35562306a36Sopenharmony_ci * dynamic interface, and not part of the *entry* retrieved from it.
35662306a36Sopenharmony_ci * Otherwise said, for a sja1105_dynamic_config_read, LOCKEDS is supposed to be
35762306a36Sopenharmony_ci * an output from the switch into the command buffer, and for a
35862306a36Sopenharmony_ci * sja1105_dynamic_config_write, the switch treats LOCKEDS as an input
35962306a36Sopenharmony_ci * (hence we can write either static, or automatically learned entries, from
36062306a36Sopenharmony_ci * the core).
36162306a36Sopenharmony_ci * But the manual contradicts itself in the last phrase where it says that on
36262306a36Sopenharmony_ci * read, LOCKEDS will be set to 1 for all FDB entries written through the
36362306a36Sopenharmony_ci * dynamic interface (therefore, the value of LOCKEDS from the
36462306a36Sopenharmony_ci * sja1105_dynamic_config_write is not really used for anything, it'll store a
36562306a36Sopenharmony_ci * 1 anyway).
36662306a36Sopenharmony_ci * This means you can't really write a FDB entry with LOCKEDS=0 (automatically
36762306a36Sopenharmony_ci * learned) into the switch, which kind of makes sense.
36862306a36Sopenharmony_ci * As for reading through the dynamic interface, it doesn't make too much sense
36962306a36Sopenharmony_ci * to put LOCKEDS into the command, since the switch will inevitably have to
37062306a36Sopenharmony_ci * ignore it (otherwise a command would be like "read the FDB entry 123, but
37162306a36Sopenharmony_ci * only if it's dynamically learned" <- well how am I supposed to know?) and
37262306a36Sopenharmony_ci * just use it as an output buffer for its findings. But guess what... that's
37362306a36Sopenharmony_ci * what the entry buffer is for!
37462306a36Sopenharmony_ci * Unfortunately, what really breaks this abstraction is the fact that it
37562306a36Sopenharmony_ci * wasn't designed having the fact in mind that the switch can output
37662306a36Sopenharmony_ci * entry-related data as writeback through the command buffer.
37762306a36Sopenharmony_ci * However, whether a FDB entry is statically or dynamically learned *is* part
37862306a36Sopenharmony_ci * of the entry and not the command data, no matter what the switch thinks.
37962306a36Sopenharmony_ci * In order to do that, we'll need to wrap around the
38062306a36Sopenharmony_ci * sja1105pqrs_l2_lookup_entry_packing from sja1105_static_config.c, and take
38162306a36Sopenharmony_ci * a peek outside of the caller-supplied @buf (the entry buffer), to reach the
38262306a36Sopenharmony_ci * command buffer.
38362306a36Sopenharmony_ci */
38462306a36Sopenharmony_cistatic size_t
38562306a36Sopenharmony_cisja1105pqrs_dyn_l2_lookup_entry_packing(void *buf, void *entry_ptr,
38662306a36Sopenharmony_ci					enum packing_op op)
38762306a36Sopenharmony_ci{
38862306a36Sopenharmony_ci	struct sja1105_l2_lookup_entry *entry = entry_ptr;
38962306a36Sopenharmony_ci	u8 *cmd = buf + SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY;
39062306a36Sopenharmony_ci	const int size = SJA1105_SIZE_DYN_CMD;
39162306a36Sopenharmony_ci
39262306a36Sopenharmony_ci	sja1105_packing(cmd, &entry->lockeds, 28, 28, size, op);
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_ci	return sja1105pqrs_l2_lookup_entry_packing(buf, entry_ptr, op);
39562306a36Sopenharmony_ci}
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_cistatic size_t sja1110_dyn_l2_lookup_entry_packing(void *buf, void *entry_ptr,
39862306a36Sopenharmony_ci						  enum packing_op op)
39962306a36Sopenharmony_ci{
40062306a36Sopenharmony_ci	struct sja1105_l2_lookup_entry *entry = entry_ptr;
40162306a36Sopenharmony_ci	u8 *cmd = buf + SJA1110_SIZE_L2_LOOKUP_ENTRY;
40262306a36Sopenharmony_ci	const int size = SJA1105_SIZE_DYN_CMD;
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_ci	sja1105_packing(cmd, &entry->lockeds, 28, 28, size, op);
40562306a36Sopenharmony_ci
40662306a36Sopenharmony_ci	return sja1110_l2_lookup_entry_packing(buf, entry_ptr, op);
40762306a36Sopenharmony_ci}
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_cistatic void
41062306a36Sopenharmony_cisja1105et_l2_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
41162306a36Sopenharmony_ci				enum packing_op op)
41262306a36Sopenharmony_ci{
41362306a36Sopenharmony_ci	u8 *p = buf + SJA1105ET_SIZE_L2_LOOKUP_ENTRY;
41462306a36Sopenharmony_ci	const int size = SJA1105_SIZE_DYN_CMD;
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_ci	sja1105_packing(p, &cmd->valid,    31, 31, size, op);
41762306a36Sopenharmony_ci	sja1105_packing(p, &cmd->rdwrset,  30, 30, size, op);
41862306a36Sopenharmony_ci	sja1105_packing(p, &cmd->errors,   29, 29, size, op);
41962306a36Sopenharmony_ci	sja1105_packing(p, &cmd->valident, 27, 27, size, op);
42062306a36Sopenharmony_ci	/* Hack - see comments above. */
42162306a36Sopenharmony_ci	sja1105_packing(buf, &cmd->index, 29, 20,
42262306a36Sopenharmony_ci			SJA1105ET_SIZE_L2_LOOKUP_ENTRY, op);
42362306a36Sopenharmony_ci}
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_cistatic size_t sja1105et_dyn_l2_lookup_entry_packing(void *buf, void *entry_ptr,
42662306a36Sopenharmony_ci						    enum packing_op op)
42762306a36Sopenharmony_ci{
42862306a36Sopenharmony_ci	struct sja1105_l2_lookup_entry *entry = entry_ptr;
42962306a36Sopenharmony_ci	u8 *cmd = buf + SJA1105ET_SIZE_L2_LOOKUP_ENTRY;
43062306a36Sopenharmony_ci	const int size = SJA1105_SIZE_DYN_CMD;
43162306a36Sopenharmony_ci
43262306a36Sopenharmony_ci	sja1105_packing(cmd, &entry->lockeds, 28, 28, size, op);
43362306a36Sopenharmony_ci
43462306a36Sopenharmony_ci	return sja1105et_l2_lookup_entry_packing(buf, entry_ptr, op);
43562306a36Sopenharmony_ci}
43662306a36Sopenharmony_ci
43762306a36Sopenharmony_cistatic void
43862306a36Sopenharmony_cisja1105et_mgmt_route_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
43962306a36Sopenharmony_ci				 enum packing_op op)
44062306a36Sopenharmony_ci{
44162306a36Sopenharmony_ci	u8 *p = buf + SJA1105ET_SIZE_L2_LOOKUP_ENTRY;
44262306a36Sopenharmony_ci	u64 mgmtroute = 1;
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_ci	sja1105et_l2_lookup_cmd_packing(buf, cmd, op);
44562306a36Sopenharmony_ci	if (op == PACK)
44662306a36Sopenharmony_ci		sja1105_pack(p, &mgmtroute, 26, 26, SJA1105_SIZE_DYN_CMD);
44762306a36Sopenharmony_ci}
44862306a36Sopenharmony_ci
44962306a36Sopenharmony_cistatic size_t sja1105et_mgmt_route_entry_packing(void *buf, void *entry_ptr,
45062306a36Sopenharmony_ci						 enum packing_op op)
45162306a36Sopenharmony_ci{
45262306a36Sopenharmony_ci	struct sja1105_mgmt_entry *entry = entry_ptr;
45362306a36Sopenharmony_ci	const size_t size = SJA1105ET_SIZE_L2_LOOKUP_ENTRY;
45462306a36Sopenharmony_ci
45562306a36Sopenharmony_ci	/* UM10944: To specify if a PTP egress timestamp shall be captured on
45662306a36Sopenharmony_ci	 * each port upon transmission of the frame, the LSB of VLANID in the
45762306a36Sopenharmony_ci	 * ENTRY field provided by the host must be set.
45862306a36Sopenharmony_ci	 * Bit 1 of VLANID then specifies the register where the timestamp for
45962306a36Sopenharmony_ci	 * this port is stored in.
46062306a36Sopenharmony_ci	 */
46162306a36Sopenharmony_ci	sja1105_packing(buf, &entry->tsreg,     85, 85, size, op);
46262306a36Sopenharmony_ci	sja1105_packing(buf, &entry->takets,    84, 84, size, op);
46362306a36Sopenharmony_ci	sja1105_packing(buf, &entry->macaddr,   83, 36, size, op);
46462306a36Sopenharmony_ci	sja1105_packing(buf, &entry->destports, 35, 31, size, op);
46562306a36Sopenharmony_ci	sja1105_packing(buf, &entry->enfport,   30, 30, size, op);
46662306a36Sopenharmony_ci	return size;
46762306a36Sopenharmony_ci}
46862306a36Sopenharmony_ci
46962306a36Sopenharmony_cistatic void
47062306a36Sopenharmony_cisja1105pqrs_mgmt_route_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
47162306a36Sopenharmony_ci				   enum packing_op op)
47262306a36Sopenharmony_ci{
47362306a36Sopenharmony_ci	u8 *p = buf + SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY;
47462306a36Sopenharmony_ci	u64 mgmtroute = 1;
47562306a36Sopenharmony_ci
47662306a36Sopenharmony_ci	sja1105pqrs_l2_lookup_cmd_packing(buf, cmd, op);
47762306a36Sopenharmony_ci	if (op == PACK)
47862306a36Sopenharmony_ci		sja1105_pack(p, &mgmtroute, 26, 26, SJA1105_SIZE_DYN_CMD);
47962306a36Sopenharmony_ci}
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_cistatic size_t sja1105pqrs_mgmt_route_entry_packing(void *buf, void *entry_ptr,
48262306a36Sopenharmony_ci						   enum packing_op op)
48362306a36Sopenharmony_ci{
48462306a36Sopenharmony_ci	const size_t size = SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY;
48562306a36Sopenharmony_ci	struct sja1105_mgmt_entry *entry = entry_ptr;
48662306a36Sopenharmony_ci
48762306a36Sopenharmony_ci	/* In P/Q/R/S, enfport got renamed to mgmtvalid, but its purpose
48862306a36Sopenharmony_ci	 * is the same (driver uses it to confirm that frame was sent).
48962306a36Sopenharmony_ci	 * So just keep the name from E/T.
49062306a36Sopenharmony_ci	 */
49162306a36Sopenharmony_ci	sja1105_packing(buf, &entry->tsreg,     71, 71, size, op);
49262306a36Sopenharmony_ci	sja1105_packing(buf, &entry->takets,    70, 70, size, op);
49362306a36Sopenharmony_ci	sja1105_packing(buf, &entry->macaddr,   69, 22, size, op);
49462306a36Sopenharmony_ci	sja1105_packing(buf, &entry->destports, 21, 17, size, op);
49562306a36Sopenharmony_ci	sja1105_packing(buf, &entry->enfport,   16, 16, size, op);
49662306a36Sopenharmony_ci	return size;
49762306a36Sopenharmony_ci}
49862306a36Sopenharmony_ci
49962306a36Sopenharmony_ci/* In E/T, entry is at addresses 0x27-0x28. There is a 4 byte gap at 0x29,
50062306a36Sopenharmony_ci * and command is at 0x2a. Similarly in P/Q/R/S there is a 1 register gap
50162306a36Sopenharmony_ci * between entry (0x2d, 0x2e) and command (0x30).
50262306a36Sopenharmony_ci */
50362306a36Sopenharmony_cistatic void
50462306a36Sopenharmony_cisja1105_vlan_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
50562306a36Sopenharmony_ci				enum packing_op op)
50662306a36Sopenharmony_ci{
50762306a36Sopenharmony_ci	u8 *p = buf + SJA1105_SIZE_VLAN_LOOKUP_ENTRY + 4;
50862306a36Sopenharmony_ci	const int size = SJA1105_SIZE_DYN_CMD;
50962306a36Sopenharmony_ci
51062306a36Sopenharmony_ci	sja1105_packing(p, &cmd->valid,    31, 31, size, op);
51162306a36Sopenharmony_ci	sja1105_packing(p, &cmd->rdwrset,  30, 30, size, op);
51262306a36Sopenharmony_ci	sja1105_packing(p, &cmd->valident, 27, 27, size, op);
51362306a36Sopenharmony_ci	/* Hack - see comments above, applied for 'vlanid' field of
51462306a36Sopenharmony_ci	 * struct sja1105_vlan_lookup_entry.
51562306a36Sopenharmony_ci	 */
51662306a36Sopenharmony_ci	sja1105_packing(buf, &cmd->index, 38, 27,
51762306a36Sopenharmony_ci			SJA1105_SIZE_VLAN_LOOKUP_ENTRY, op);
51862306a36Sopenharmony_ci}
51962306a36Sopenharmony_ci
52062306a36Sopenharmony_ci/* In SJA1110 there is no gap between the command and the data, yay... */
52162306a36Sopenharmony_cistatic void
52262306a36Sopenharmony_cisja1110_vlan_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
52362306a36Sopenharmony_ci				enum packing_op op)
52462306a36Sopenharmony_ci{
52562306a36Sopenharmony_ci	u8 *p = buf + SJA1110_SIZE_VLAN_LOOKUP_ENTRY;
52662306a36Sopenharmony_ci	const int size = SJA1105_SIZE_DYN_CMD;
52762306a36Sopenharmony_ci	u64 type_entry = 0;
52862306a36Sopenharmony_ci
52962306a36Sopenharmony_ci	sja1105_packing(p, &cmd->valid,   31, 31, size, op);
53062306a36Sopenharmony_ci	sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op);
53162306a36Sopenharmony_ci	sja1105_packing(p, &cmd->errors,  29, 29, size, op);
53262306a36Sopenharmony_ci	/* Hack: treat 'vlanid' field of struct sja1105_vlan_lookup_entry as
53362306a36Sopenharmony_ci	 * cmd->index.
53462306a36Sopenharmony_ci	 */
53562306a36Sopenharmony_ci	sja1105_packing(buf, &cmd->index, 38, 27,
53662306a36Sopenharmony_ci			SJA1110_SIZE_VLAN_LOOKUP_ENTRY, op);
53762306a36Sopenharmony_ci
53862306a36Sopenharmony_ci	/* But the VALIDENT bit has disappeared, now we are supposed to
53962306a36Sopenharmony_ci	 * invalidate an entry through the TYPE_ENTRY field of the entry..
54062306a36Sopenharmony_ci	 * This is a hack to transform the non-zero quality of the TYPE_ENTRY
54162306a36Sopenharmony_ci	 * field into a VALIDENT bit.
54262306a36Sopenharmony_ci	 */
54362306a36Sopenharmony_ci	if (op == PACK && !cmd->valident) {
54462306a36Sopenharmony_ci		sja1105_packing(buf, &type_entry, 40, 39,
54562306a36Sopenharmony_ci				SJA1110_SIZE_VLAN_LOOKUP_ENTRY, PACK);
54662306a36Sopenharmony_ci	} else if (op == UNPACK) {
54762306a36Sopenharmony_ci		sja1105_packing(buf, &type_entry, 40, 39,
54862306a36Sopenharmony_ci				SJA1110_SIZE_VLAN_LOOKUP_ENTRY, UNPACK);
54962306a36Sopenharmony_ci		cmd->valident = !!type_entry;
55062306a36Sopenharmony_ci	}
55162306a36Sopenharmony_ci}
55262306a36Sopenharmony_ci
55362306a36Sopenharmony_cistatic void
55462306a36Sopenharmony_cisja1105_l2_forwarding_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
55562306a36Sopenharmony_ci				  enum packing_op op)
55662306a36Sopenharmony_ci{
55762306a36Sopenharmony_ci	u8 *p = buf + SJA1105_SIZE_L2_FORWARDING_ENTRY;
55862306a36Sopenharmony_ci	const int size = SJA1105_SIZE_DYN_CMD;
55962306a36Sopenharmony_ci
56062306a36Sopenharmony_ci	sja1105_packing(p, &cmd->valid,   31, 31, size, op);
56162306a36Sopenharmony_ci	sja1105_packing(p, &cmd->errors,  30, 30, size, op);
56262306a36Sopenharmony_ci	sja1105_packing(p, &cmd->rdwrset, 29, 29, size, op);
56362306a36Sopenharmony_ci	sja1105_packing(p, &cmd->index,    4,  0, size, op);
56462306a36Sopenharmony_ci}
56562306a36Sopenharmony_ci
56662306a36Sopenharmony_cistatic void
56762306a36Sopenharmony_cisja1110_l2_forwarding_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
56862306a36Sopenharmony_ci				  enum packing_op op)
56962306a36Sopenharmony_ci{
57062306a36Sopenharmony_ci	u8 *p = buf + SJA1105_SIZE_L2_FORWARDING_ENTRY;
57162306a36Sopenharmony_ci	const int size = SJA1105_SIZE_DYN_CMD;
57262306a36Sopenharmony_ci
57362306a36Sopenharmony_ci	sja1105_packing(p, &cmd->valid,   31, 31, size, op);
57462306a36Sopenharmony_ci	sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op);
57562306a36Sopenharmony_ci	sja1105_packing(p, &cmd->errors,  29, 29, size, op);
57662306a36Sopenharmony_ci	sja1105_packing(p, &cmd->index,    4,  0, size, op);
57762306a36Sopenharmony_ci}
57862306a36Sopenharmony_ci
57962306a36Sopenharmony_cistatic void
58062306a36Sopenharmony_cisja1105et_mac_config_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
58162306a36Sopenharmony_ci				 enum packing_op op)
58262306a36Sopenharmony_ci{
58362306a36Sopenharmony_ci	const int size = SJA1105_SIZE_DYN_CMD;
58462306a36Sopenharmony_ci	/* Yup, user manual definitions are reversed */
58562306a36Sopenharmony_ci	u8 *reg1 = buf + 4;
58662306a36Sopenharmony_ci
58762306a36Sopenharmony_ci	sja1105_packing(reg1, &cmd->valid, 31, 31, size, op);
58862306a36Sopenharmony_ci	sja1105_packing(reg1, &cmd->index, 26, 24, size, op);
58962306a36Sopenharmony_ci}
59062306a36Sopenharmony_ci
59162306a36Sopenharmony_cistatic size_t sja1105et_mac_config_entry_packing(void *buf, void *entry_ptr,
59262306a36Sopenharmony_ci						 enum packing_op op)
59362306a36Sopenharmony_ci{
59462306a36Sopenharmony_ci	const int size = SJA1105ET_SIZE_MAC_CONFIG_DYN_ENTRY;
59562306a36Sopenharmony_ci	struct sja1105_mac_config_entry *entry = entry_ptr;
59662306a36Sopenharmony_ci	/* Yup, user manual definitions are reversed */
59762306a36Sopenharmony_ci	u8 *reg1 = buf + 4;
59862306a36Sopenharmony_ci	u8 *reg2 = buf;
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_ci	sja1105_packing(reg1, &entry->speed,     30, 29, size, op);
60162306a36Sopenharmony_ci	sja1105_packing(reg1, &entry->drpdtag,   23, 23, size, op);
60262306a36Sopenharmony_ci	sja1105_packing(reg1, &entry->drpuntag,  22, 22, size, op);
60362306a36Sopenharmony_ci	sja1105_packing(reg1, &entry->retag,     21, 21, size, op);
60462306a36Sopenharmony_ci	sja1105_packing(reg1, &entry->dyn_learn, 20, 20, size, op);
60562306a36Sopenharmony_ci	sja1105_packing(reg1, &entry->egress,    19, 19, size, op);
60662306a36Sopenharmony_ci	sja1105_packing(reg1, &entry->ingress,   18, 18, size, op);
60762306a36Sopenharmony_ci	sja1105_packing(reg1, &entry->ing_mirr,  17, 17, size, op);
60862306a36Sopenharmony_ci	sja1105_packing(reg1, &entry->egr_mirr,  16, 16, size, op);
60962306a36Sopenharmony_ci	sja1105_packing(reg1, &entry->vlanprio,  14, 12, size, op);
61062306a36Sopenharmony_ci	sja1105_packing(reg1, &entry->vlanid,    11,  0, size, op);
61162306a36Sopenharmony_ci	sja1105_packing(reg2, &entry->tp_delin,  31, 16, size, op);
61262306a36Sopenharmony_ci	sja1105_packing(reg2, &entry->tp_delout, 15,  0, size, op);
61362306a36Sopenharmony_ci	/* MAC configuration table entries which can't be reconfigured:
61462306a36Sopenharmony_ci	 * top, base, enabled, ifg, maxage, drpnona664
61562306a36Sopenharmony_ci	 */
61662306a36Sopenharmony_ci	/* Bogus return value, not used anywhere */
61762306a36Sopenharmony_ci	return 0;
61862306a36Sopenharmony_ci}
61962306a36Sopenharmony_ci
62062306a36Sopenharmony_cistatic void
62162306a36Sopenharmony_cisja1105pqrs_mac_config_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
62262306a36Sopenharmony_ci				   enum packing_op op)
62362306a36Sopenharmony_ci{
62462306a36Sopenharmony_ci	const int size = SJA1105ET_SIZE_MAC_CONFIG_DYN_ENTRY;
62562306a36Sopenharmony_ci	u8 *p = buf + SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY;
62662306a36Sopenharmony_ci
62762306a36Sopenharmony_ci	sja1105_packing(p, &cmd->valid,   31, 31, size, op);
62862306a36Sopenharmony_ci	sja1105_packing(p, &cmd->errors,  30, 30, size, op);
62962306a36Sopenharmony_ci	sja1105_packing(p, &cmd->rdwrset, 29, 29, size, op);
63062306a36Sopenharmony_ci	sja1105_packing(p, &cmd->index,    2,  0, size, op);
63162306a36Sopenharmony_ci}
63262306a36Sopenharmony_ci
63362306a36Sopenharmony_cistatic void
63462306a36Sopenharmony_cisja1110_mac_config_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
63562306a36Sopenharmony_ci			       enum packing_op op)
63662306a36Sopenharmony_ci{
63762306a36Sopenharmony_ci	u8 *p = buf + SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY;
63862306a36Sopenharmony_ci	const int size = SJA1105_SIZE_DYN_CMD;
63962306a36Sopenharmony_ci
64062306a36Sopenharmony_ci	sja1105_packing(p, &cmd->valid,   31, 31, size, op);
64162306a36Sopenharmony_ci	sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op);
64262306a36Sopenharmony_ci	sja1105_packing(p, &cmd->errors,  29, 29, size, op);
64362306a36Sopenharmony_ci	sja1105_packing(p, &cmd->index,    3,  0, size, op);
64462306a36Sopenharmony_ci}
64562306a36Sopenharmony_ci
64662306a36Sopenharmony_cistatic void
64762306a36Sopenharmony_cisja1105et_l2_lookup_params_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
64862306a36Sopenharmony_ci				       enum packing_op op)
64962306a36Sopenharmony_ci{
65062306a36Sopenharmony_ci	sja1105_packing(buf, &cmd->valid, 31, 31,
65162306a36Sopenharmony_ci			SJA1105ET_SIZE_L2_LOOKUP_PARAMS_DYN_CMD, op);
65262306a36Sopenharmony_ci}
65362306a36Sopenharmony_ci
65462306a36Sopenharmony_cistatic size_t
65562306a36Sopenharmony_cisja1105et_l2_lookup_params_entry_packing(void *buf, void *entry_ptr,
65662306a36Sopenharmony_ci					 enum packing_op op)
65762306a36Sopenharmony_ci{
65862306a36Sopenharmony_ci	struct sja1105_l2_lookup_params_entry *entry = entry_ptr;
65962306a36Sopenharmony_ci
66062306a36Sopenharmony_ci	sja1105_packing(buf, &entry->poly, 7, 0,
66162306a36Sopenharmony_ci			SJA1105ET_SIZE_L2_LOOKUP_PARAMS_DYN_CMD, op);
66262306a36Sopenharmony_ci	/* Bogus return value, not used anywhere */
66362306a36Sopenharmony_ci	return 0;
66462306a36Sopenharmony_ci}
66562306a36Sopenharmony_ci
66662306a36Sopenharmony_cistatic void
66762306a36Sopenharmony_cisja1105pqrs_l2_lookup_params_cmd_packing(void *buf,
66862306a36Sopenharmony_ci					 struct sja1105_dyn_cmd *cmd,
66962306a36Sopenharmony_ci					 enum packing_op op)
67062306a36Sopenharmony_ci{
67162306a36Sopenharmony_ci	u8 *p = buf + SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_ENTRY;
67262306a36Sopenharmony_ci	const int size = SJA1105_SIZE_DYN_CMD;
67362306a36Sopenharmony_ci
67462306a36Sopenharmony_ci	sja1105_packing(p, &cmd->valid,   31, 31, size, op);
67562306a36Sopenharmony_ci	sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op);
67662306a36Sopenharmony_ci}
67762306a36Sopenharmony_ci
67862306a36Sopenharmony_cistatic void
67962306a36Sopenharmony_cisja1110_l2_lookup_params_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
68062306a36Sopenharmony_ci				     enum packing_op op)
68162306a36Sopenharmony_ci{
68262306a36Sopenharmony_ci	u8 *p = buf + SJA1110_SIZE_L2_LOOKUP_PARAMS_ENTRY;
68362306a36Sopenharmony_ci	const int size = SJA1105_SIZE_DYN_CMD;
68462306a36Sopenharmony_ci
68562306a36Sopenharmony_ci	sja1105_packing(p, &cmd->valid,   31, 31, size, op);
68662306a36Sopenharmony_ci	sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op);
68762306a36Sopenharmony_ci	sja1105_packing(p, &cmd->errors,  29, 29, size, op);
68862306a36Sopenharmony_ci}
68962306a36Sopenharmony_ci
69062306a36Sopenharmony_cistatic void
69162306a36Sopenharmony_cisja1105et_general_params_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
69262306a36Sopenharmony_ci				     enum packing_op op)
69362306a36Sopenharmony_ci{
69462306a36Sopenharmony_ci	const int size = SJA1105ET_SIZE_GENERAL_PARAMS_DYN_CMD;
69562306a36Sopenharmony_ci
69662306a36Sopenharmony_ci	sja1105_packing(buf, &cmd->valid,  31, 31, size, op);
69762306a36Sopenharmony_ci	sja1105_packing(buf, &cmd->errors, 30, 30, size, op);
69862306a36Sopenharmony_ci}
69962306a36Sopenharmony_ci
70062306a36Sopenharmony_cistatic size_t
70162306a36Sopenharmony_cisja1105et_general_params_entry_packing(void *buf, void *entry_ptr,
70262306a36Sopenharmony_ci				       enum packing_op op)
70362306a36Sopenharmony_ci{
70462306a36Sopenharmony_ci	struct sja1105_general_params_entry *entry = entry_ptr;
70562306a36Sopenharmony_ci	const int size = SJA1105ET_SIZE_GENERAL_PARAMS_DYN_CMD;
70662306a36Sopenharmony_ci
70762306a36Sopenharmony_ci	sja1105_packing(buf, &entry->mirr_port, 2, 0, size, op);
70862306a36Sopenharmony_ci	/* Bogus return value, not used anywhere */
70962306a36Sopenharmony_ci	return 0;
71062306a36Sopenharmony_ci}
71162306a36Sopenharmony_ci
71262306a36Sopenharmony_cistatic void
71362306a36Sopenharmony_cisja1105pqrs_general_params_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
71462306a36Sopenharmony_ci				       enum packing_op op)
71562306a36Sopenharmony_ci{
71662306a36Sopenharmony_ci	u8 *p = buf + SJA1105PQRS_SIZE_GENERAL_PARAMS_ENTRY;
71762306a36Sopenharmony_ci	const int size = SJA1105_SIZE_DYN_CMD;
71862306a36Sopenharmony_ci
71962306a36Sopenharmony_ci	sja1105_packing(p, &cmd->valid,   31, 31, size, op);
72062306a36Sopenharmony_ci	sja1105_packing(p, &cmd->errors,  30, 30, size, op);
72162306a36Sopenharmony_ci	sja1105_packing(p, &cmd->rdwrset, 28, 28, size, op);
72262306a36Sopenharmony_ci}
72362306a36Sopenharmony_ci
72462306a36Sopenharmony_cistatic void
72562306a36Sopenharmony_cisja1110_general_params_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
72662306a36Sopenharmony_ci				   enum packing_op op)
72762306a36Sopenharmony_ci{
72862306a36Sopenharmony_ci	u8 *p = buf + SJA1110_SIZE_GENERAL_PARAMS_ENTRY;
72962306a36Sopenharmony_ci	const int size = SJA1105_SIZE_DYN_CMD;
73062306a36Sopenharmony_ci
73162306a36Sopenharmony_ci	sja1105_packing(p, &cmd->valid,   31, 31, size, op);
73262306a36Sopenharmony_ci	sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op);
73362306a36Sopenharmony_ci	sja1105_packing(p, &cmd->errors,  29, 29, size, op);
73462306a36Sopenharmony_ci}
73562306a36Sopenharmony_ci
73662306a36Sopenharmony_cistatic void
73762306a36Sopenharmony_cisja1105pqrs_avb_params_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
73862306a36Sopenharmony_ci				   enum packing_op op)
73962306a36Sopenharmony_ci{
74062306a36Sopenharmony_ci	u8 *p = buf + SJA1105PQRS_SIZE_AVB_PARAMS_ENTRY;
74162306a36Sopenharmony_ci	const int size = SJA1105_SIZE_DYN_CMD;
74262306a36Sopenharmony_ci
74362306a36Sopenharmony_ci	sja1105_packing(p, &cmd->valid,   31, 31, size, op);
74462306a36Sopenharmony_ci	sja1105_packing(p, &cmd->errors,  30, 30, size, op);
74562306a36Sopenharmony_ci	sja1105_packing(p, &cmd->rdwrset, 29, 29, size, op);
74662306a36Sopenharmony_ci}
74762306a36Sopenharmony_ci
74862306a36Sopenharmony_cistatic void
74962306a36Sopenharmony_cisja1105_retagging_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
75062306a36Sopenharmony_ci			      enum packing_op op)
75162306a36Sopenharmony_ci{
75262306a36Sopenharmony_ci	u8 *p = buf + SJA1105_SIZE_RETAGGING_ENTRY;
75362306a36Sopenharmony_ci	const int size = SJA1105_SIZE_DYN_CMD;
75462306a36Sopenharmony_ci
75562306a36Sopenharmony_ci	sja1105_packing(p, &cmd->valid,    31, 31, size, op);
75662306a36Sopenharmony_ci	sja1105_packing(p, &cmd->errors,   30, 30, size, op);
75762306a36Sopenharmony_ci	sja1105_packing(p, &cmd->valident, 29, 29, size, op);
75862306a36Sopenharmony_ci	sja1105_packing(p, &cmd->rdwrset,  28, 28, size, op);
75962306a36Sopenharmony_ci	sja1105_packing(p, &cmd->index,     5,  0, size, op);
76062306a36Sopenharmony_ci}
76162306a36Sopenharmony_ci
76262306a36Sopenharmony_cistatic void
76362306a36Sopenharmony_cisja1110_retagging_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
76462306a36Sopenharmony_ci			      enum packing_op op)
76562306a36Sopenharmony_ci{
76662306a36Sopenharmony_ci	u8 *p = buf + SJA1105_SIZE_RETAGGING_ENTRY;
76762306a36Sopenharmony_ci	const int size = SJA1105_SIZE_DYN_CMD;
76862306a36Sopenharmony_ci
76962306a36Sopenharmony_ci	sja1105_packing(p, &cmd->valid,    31, 31, size, op);
77062306a36Sopenharmony_ci	sja1105_packing(p, &cmd->rdwrset,  30, 30, size, op);
77162306a36Sopenharmony_ci	sja1105_packing(p, &cmd->errors,   29, 29, size, op);
77262306a36Sopenharmony_ci	sja1105_packing(p, &cmd->valident, 28, 28, size, op);
77362306a36Sopenharmony_ci	sja1105_packing(p, &cmd->index,     4,  0, size, op);
77462306a36Sopenharmony_ci}
77562306a36Sopenharmony_ci
77662306a36Sopenharmony_cistatic void sja1105et_cbs_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
77762306a36Sopenharmony_ci				      enum packing_op op)
77862306a36Sopenharmony_ci{
77962306a36Sopenharmony_ci	u8 *p = buf + SJA1105ET_SIZE_CBS_ENTRY;
78062306a36Sopenharmony_ci	const int size = SJA1105_SIZE_DYN_CMD;
78162306a36Sopenharmony_ci
78262306a36Sopenharmony_ci	sja1105_packing(p, &cmd->valid, 31, 31, size, op);
78362306a36Sopenharmony_ci	sja1105_packing(p, &cmd->index, 19, 16, size, op);
78462306a36Sopenharmony_ci}
78562306a36Sopenharmony_ci
78662306a36Sopenharmony_cistatic size_t sja1105et_cbs_entry_packing(void *buf, void *entry_ptr,
78762306a36Sopenharmony_ci					  enum packing_op op)
78862306a36Sopenharmony_ci{
78962306a36Sopenharmony_ci	const size_t size = SJA1105ET_SIZE_CBS_ENTRY;
79062306a36Sopenharmony_ci	struct sja1105_cbs_entry *entry = entry_ptr;
79162306a36Sopenharmony_ci	u8 *cmd = buf + size;
79262306a36Sopenharmony_ci	u32 *p = buf;
79362306a36Sopenharmony_ci
79462306a36Sopenharmony_ci	sja1105_packing(cmd, &entry->port, 5, 3, SJA1105_SIZE_DYN_CMD, op);
79562306a36Sopenharmony_ci	sja1105_packing(cmd, &entry->prio, 2, 0, SJA1105_SIZE_DYN_CMD, op);
79662306a36Sopenharmony_ci	sja1105_packing(p + 3, &entry->credit_lo,  31, 0, size, op);
79762306a36Sopenharmony_ci	sja1105_packing(p + 2, &entry->credit_hi,  31, 0, size, op);
79862306a36Sopenharmony_ci	sja1105_packing(p + 1, &entry->send_slope, 31, 0, size, op);
79962306a36Sopenharmony_ci	sja1105_packing(p + 0, &entry->idle_slope, 31, 0, size, op);
80062306a36Sopenharmony_ci	return size;
80162306a36Sopenharmony_ci}
80262306a36Sopenharmony_ci
80362306a36Sopenharmony_cistatic void sja1105pqrs_cbs_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
80462306a36Sopenharmony_ci					enum packing_op op)
80562306a36Sopenharmony_ci{
80662306a36Sopenharmony_ci	u8 *p = buf + SJA1105PQRS_SIZE_CBS_ENTRY;
80762306a36Sopenharmony_ci	const int size = SJA1105_SIZE_DYN_CMD;
80862306a36Sopenharmony_ci
80962306a36Sopenharmony_ci	sja1105_packing(p, &cmd->valid,   31, 31, size, op);
81062306a36Sopenharmony_ci	sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op);
81162306a36Sopenharmony_ci	sja1105_packing(p, &cmd->errors,  29, 29, size, op);
81262306a36Sopenharmony_ci	sja1105_packing(p, &cmd->index,    3,  0, size, op);
81362306a36Sopenharmony_ci}
81462306a36Sopenharmony_ci
81562306a36Sopenharmony_cistatic void sja1110_cbs_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
81662306a36Sopenharmony_ci				    enum packing_op op)
81762306a36Sopenharmony_ci{
81862306a36Sopenharmony_ci	u8 *p = buf + SJA1105PQRS_SIZE_CBS_ENTRY;
81962306a36Sopenharmony_ci	const int size = SJA1105_SIZE_DYN_CMD;
82062306a36Sopenharmony_ci
82162306a36Sopenharmony_ci	sja1105_packing(p, &cmd->valid,   31, 31, size, op);
82262306a36Sopenharmony_ci	sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op);
82362306a36Sopenharmony_ci	sja1105_packing(p, &cmd->errors,  29, 29, size, op);
82462306a36Sopenharmony_ci	sja1105_packing(p, &cmd->index,    7,  0, size, op);
82562306a36Sopenharmony_ci}
82662306a36Sopenharmony_ci
82762306a36Sopenharmony_cistatic size_t sja1105pqrs_cbs_entry_packing(void *buf, void *entry_ptr,
82862306a36Sopenharmony_ci					    enum packing_op op)
82962306a36Sopenharmony_ci{
83062306a36Sopenharmony_ci	const size_t size = SJA1105PQRS_SIZE_CBS_ENTRY;
83162306a36Sopenharmony_ci	struct sja1105_cbs_entry *entry = entry_ptr;
83262306a36Sopenharmony_ci
83362306a36Sopenharmony_ci	sja1105_packing(buf, &entry->port,      159, 157, size, op);
83462306a36Sopenharmony_ci	sja1105_packing(buf, &entry->prio,      156, 154, size, op);
83562306a36Sopenharmony_ci	sja1105_packing(buf, &entry->credit_lo, 153, 122, size, op);
83662306a36Sopenharmony_ci	sja1105_packing(buf, &entry->credit_hi, 121,  90, size, op);
83762306a36Sopenharmony_ci	sja1105_packing(buf, &entry->send_slope, 89,  58, size, op);
83862306a36Sopenharmony_ci	sja1105_packing(buf, &entry->idle_slope, 57,  26, size, op);
83962306a36Sopenharmony_ci	return size;
84062306a36Sopenharmony_ci}
84162306a36Sopenharmony_ci
84262306a36Sopenharmony_cistatic size_t sja1110_cbs_entry_packing(void *buf, void *entry_ptr,
84362306a36Sopenharmony_ci					enum packing_op op)
84462306a36Sopenharmony_ci{
84562306a36Sopenharmony_ci	const size_t size = SJA1105PQRS_SIZE_CBS_ENTRY;
84662306a36Sopenharmony_ci	struct sja1105_cbs_entry *entry = entry_ptr;
84762306a36Sopenharmony_ci	u64 entry_type = SJA1110_CBS_SHAPER;
84862306a36Sopenharmony_ci
84962306a36Sopenharmony_ci	sja1105_packing(buf, &entry_type,       159, 159, size, op);
85062306a36Sopenharmony_ci	sja1105_packing(buf, &entry->credit_lo, 151, 120, size, op);
85162306a36Sopenharmony_ci	sja1105_packing(buf, &entry->credit_hi, 119,  88, size, op);
85262306a36Sopenharmony_ci	sja1105_packing(buf, &entry->send_slope, 87,  56, size, op);
85362306a36Sopenharmony_ci	sja1105_packing(buf, &entry->idle_slope, 55,  24, size, op);
85462306a36Sopenharmony_ci	return size;
85562306a36Sopenharmony_ci}
85662306a36Sopenharmony_ci
85762306a36Sopenharmony_cistatic void sja1110_dummy_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
85862306a36Sopenharmony_ci				      enum packing_op op)
85962306a36Sopenharmony_ci{
86062306a36Sopenharmony_ci}
86162306a36Sopenharmony_ci
86262306a36Sopenharmony_cistatic void
86362306a36Sopenharmony_cisja1110_l2_policing_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
86462306a36Sopenharmony_ci				enum packing_op op)
86562306a36Sopenharmony_ci{
86662306a36Sopenharmony_ci	u8 *p = buf + SJA1105_SIZE_L2_POLICING_ENTRY;
86762306a36Sopenharmony_ci	const int size = SJA1105_SIZE_DYN_CMD;
86862306a36Sopenharmony_ci
86962306a36Sopenharmony_ci	sja1105_packing(p, &cmd->valid,   31, 31, size, op);
87062306a36Sopenharmony_ci	sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op);
87162306a36Sopenharmony_ci	sja1105_packing(p, &cmd->errors,  29, 29, size, op);
87262306a36Sopenharmony_ci	sja1105_packing(p, &cmd->index,    6,  0, size, op);
87362306a36Sopenharmony_ci}
87462306a36Sopenharmony_ci
87562306a36Sopenharmony_ci#define OP_READ		BIT(0)
87662306a36Sopenharmony_ci#define OP_WRITE	BIT(1)
87762306a36Sopenharmony_ci#define OP_DEL		BIT(2)
87862306a36Sopenharmony_ci#define OP_SEARCH	BIT(3)
87962306a36Sopenharmony_ci#define OP_VALID_ANYWAY	BIT(4)
88062306a36Sopenharmony_ci
88162306a36Sopenharmony_ci/* SJA1105E/T: First generation */
88262306a36Sopenharmony_ciconst struct sja1105_dynamic_table_ops sja1105et_dyn_ops[BLK_IDX_MAX_DYN] = {
88362306a36Sopenharmony_ci	[BLK_IDX_VL_LOOKUP] = {
88462306a36Sopenharmony_ci		.entry_packing = sja1105et_vl_lookup_entry_packing,
88562306a36Sopenharmony_ci		.cmd_packing = sja1105et_vl_lookup_cmd_packing,
88662306a36Sopenharmony_ci		.access = OP_WRITE,
88762306a36Sopenharmony_ci		.max_entry_count = SJA1105_MAX_VL_LOOKUP_COUNT,
88862306a36Sopenharmony_ci		.packed_size = SJA1105ET_SIZE_VL_LOOKUP_DYN_CMD,
88962306a36Sopenharmony_ci		.addr = 0x35,
89062306a36Sopenharmony_ci	},
89162306a36Sopenharmony_ci	[BLK_IDX_L2_LOOKUP] = {
89262306a36Sopenharmony_ci		.entry_packing = sja1105et_dyn_l2_lookup_entry_packing,
89362306a36Sopenharmony_ci		.cmd_packing = sja1105et_l2_lookup_cmd_packing,
89462306a36Sopenharmony_ci		.access = (OP_READ | OP_WRITE | OP_DEL),
89562306a36Sopenharmony_ci		.max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT,
89662306a36Sopenharmony_ci		.packed_size = SJA1105ET_SIZE_L2_LOOKUP_DYN_CMD,
89762306a36Sopenharmony_ci		.addr = 0x20,
89862306a36Sopenharmony_ci	},
89962306a36Sopenharmony_ci	[BLK_IDX_MGMT_ROUTE] = {
90062306a36Sopenharmony_ci		.entry_packing = sja1105et_mgmt_route_entry_packing,
90162306a36Sopenharmony_ci		.cmd_packing = sja1105et_mgmt_route_cmd_packing,
90262306a36Sopenharmony_ci		.access = (OP_READ | OP_WRITE | OP_VALID_ANYWAY),
90362306a36Sopenharmony_ci		.max_entry_count = SJA1105_NUM_PORTS,
90462306a36Sopenharmony_ci		.packed_size = SJA1105ET_SIZE_L2_LOOKUP_DYN_CMD,
90562306a36Sopenharmony_ci		.addr = 0x20,
90662306a36Sopenharmony_ci	},
90762306a36Sopenharmony_ci	[BLK_IDX_VLAN_LOOKUP] = {
90862306a36Sopenharmony_ci		.entry_packing = sja1105_vlan_lookup_entry_packing,
90962306a36Sopenharmony_ci		.cmd_packing = sja1105_vlan_lookup_cmd_packing,
91062306a36Sopenharmony_ci		.access = (OP_WRITE | OP_DEL),
91162306a36Sopenharmony_ci		.max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT,
91262306a36Sopenharmony_ci		.packed_size = SJA1105_SIZE_VLAN_LOOKUP_DYN_CMD,
91362306a36Sopenharmony_ci		.addr = 0x27,
91462306a36Sopenharmony_ci	},
91562306a36Sopenharmony_ci	[BLK_IDX_L2_FORWARDING] = {
91662306a36Sopenharmony_ci		.entry_packing = sja1105_l2_forwarding_entry_packing,
91762306a36Sopenharmony_ci		.cmd_packing = sja1105_l2_forwarding_cmd_packing,
91862306a36Sopenharmony_ci		.max_entry_count = SJA1105_MAX_L2_FORWARDING_COUNT,
91962306a36Sopenharmony_ci		.access = OP_WRITE,
92062306a36Sopenharmony_ci		.packed_size = SJA1105_SIZE_L2_FORWARDING_DYN_CMD,
92162306a36Sopenharmony_ci		.addr = 0x24,
92262306a36Sopenharmony_ci	},
92362306a36Sopenharmony_ci	[BLK_IDX_MAC_CONFIG] = {
92462306a36Sopenharmony_ci		.entry_packing = sja1105et_mac_config_entry_packing,
92562306a36Sopenharmony_ci		.cmd_packing = sja1105et_mac_config_cmd_packing,
92662306a36Sopenharmony_ci		.max_entry_count = SJA1105_MAX_MAC_CONFIG_COUNT,
92762306a36Sopenharmony_ci		.access = OP_WRITE,
92862306a36Sopenharmony_ci		.packed_size = SJA1105ET_SIZE_MAC_CONFIG_DYN_CMD,
92962306a36Sopenharmony_ci		.addr = 0x36,
93062306a36Sopenharmony_ci	},
93162306a36Sopenharmony_ci	[BLK_IDX_L2_LOOKUP_PARAMS] = {
93262306a36Sopenharmony_ci		.entry_packing = sja1105et_l2_lookup_params_entry_packing,
93362306a36Sopenharmony_ci		.cmd_packing = sja1105et_l2_lookup_params_cmd_packing,
93462306a36Sopenharmony_ci		.max_entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT,
93562306a36Sopenharmony_ci		.access = OP_WRITE,
93662306a36Sopenharmony_ci		.packed_size = SJA1105ET_SIZE_L2_LOOKUP_PARAMS_DYN_CMD,
93762306a36Sopenharmony_ci		.addr = 0x38,
93862306a36Sopenharmony_ci	},
93962306a36Sopenharmony_ci	[BLK_IDX_GENERAL_PARAMS] = {
94062306a36Sopenharmony_ci		.entry_packing = sja1105et_general_params_entry_packing,
94162306a36Sopenharmony_ci		.cmd_packing = sja1105et_general_params_cmd_packing,
94262306a36Sopenharmony_ci		.max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT,
94362306a36Sopenharmony_ci		.access = OP_WRITE,
94462306a36Sopenharmony_ci		.packed_size = SJA1105ET_SIZE_GENERAL_PARAMS_DYN_CMD,
94562306a36Sopenharmony_ci		.addr = 0x34,
94662306a36Sopenharmony_ci	},
94762306a36Sopenharmony_ci	[BLK_IDX_RETAGGING] = {
94862306a36Sopenharmony_ci		.entry_packing = sja1105_retagging_entry_packing,
94962306a36Sopenharmony_ci		.cmd_packing = sja1105_retagging_cmd_packing,
95062306a36Sopenharmony_ci		.max_entry_count = SJA1105_MAX_RETAGGING_COUNT,
95162306a36Sopenharmony_ci		.access = (OP_WRITE | OP_DEL),
95262306a36Sopenharmony_ci		.packed_size = SJA1105_SIZE_RETAGGING_DYN_CMD,
95362306a36Sopenharmony_ci		.addr = 0x31,
95462306a36Sopenharmony_ci	},
95562306a36Sopenharmony_ci	[BLK_IDX_CBS] = {
95662306a36Sopenharmony_ci		.entry_packing = sja1105et_cbs_entry_packing,
95762306a36Sopenharmony_ci		.cmd_packing = sja1105et_cbs_cmd_packing,
95862306a36Sopenharmony_ci		.max_entry_count = SJA1105ET_MAX_CBS_COUNT,
95962306a36Sopenharmony_ci		.access = OP_WRITE,
96062306a36Sopenharmony_ci		.packed_size = SJA1105ET_SIZE_CBS_DYN_CMD,
96162306a36Sopenharmony_ci		.addr = 0x2c,
96262306a36Sopenharmony_ci	},
96362306a36Sopenharmony_ci};
96462306a36Sopenharmony_ci
96562306a36Sopenharmony_ci/* SJA1105P/Q/R/S: Second generation */
96662306a36Sopenharmony_ciconst struct sja1105_dynamic_table_ops sja1105pqrs_dyn_ops[BLK_IDX_MAX_DYN] = {
96762306a36Sopenharmony_ci	[BLK_IDX_VL_LOOKUP] = {
96862306a36Sopenharmony_ci		.entry_packing = sja1105_vl_lookup_entry_packing,
96962306a36Sopenharmony_ci		.cmd_packing = sja1105pqrs_vl_lookup_cmd_packing,
97062306a36Sopenharmony_ci		.access = (OP_READ | OP_WRITE),
97162306a36Sopenharmony_ci		.max_entry_count = SJA1105_MAX_VL_LOOKUP_COUNT,
97262306a36Sopenharmony_ci		.packed_size = SJA1105PQRS_SIZE_VL_LOOKUP_DYN_CMD,
97362306a36Sopenharmony_ci		.addr = 0x47,
97462306a36Sopenharmony_ci	},
97562306a36Sopenharmony_ci	[BLK_IDX_L2_LOOKUP] = {
97662306a36Sopenharmony_ci		.entry_packing = sja1105pqrs_dyn_l2_lookup_entry_packing,
97762306a36Sopenharmony_ci		.cmd_packing = sja1105pqrs_l2_lookup_cmd_packing,
97862306a36Sopenharmony_ci		.access = (OP_READ | OP_WRITE | OP_DEL | OP_SEARCH),
97962306a36Sopenharmony_ci		.max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT,
98062306a36Sopenharmony_ci		.packed_size = SJA1105PQRS_SIZE_L2_LOOKUP_DYN_CMD,
98162306a36Sopenharmony_ci		.addr = 0x24,
98262306a36Sopenharmony_ci	},
98362306a36Sopenharmony_ci	[BLK_IDX_MGMT_ROUTE] = {
98462306a36Sopenharmony_ci		.entry_packing = sja1105pqrs_mgmt_route_entry_packing,
98562306a36Sopenharmony_ci		.cmd_packing = sja1105pqrs_mgmt_route_cmd_packing,
98662306a36Sopenharmony_ci		.access = (OP_READ | OP_WRITE | OP_DEL | OP_SEARCH | OP_VALID_ANYWAY),
98762306a36Sopenharmony_ci		.max_entry_count = SJA1105_NUM_PORTS,
98862306a36Sopenharmony_ci		.packed_size = SJA1105PQRS_SIZE_L2_LOOKUP_DYN_CMD,
98962306a36Sopenharmony_ci		.addr = 0x24,
99062306a36Sopenharmony_ci	},
99162306a36Sopenharmony_ci	[BLK_IDX_VLAN_LOOKUP] = {
99262306a36Sopenharmony_ci		.entry_packing = sja1105_vlan_lookup_entry_packing,
99362306a36Sopenharmony_ci		.cmd_packing = sja1105_vlan_lookup_cmd_packing,
99462306a36Sopenharmony_ci		.access = (OP_READ | OP_WRITE | OP_DEL),
99562306a36Sopenharmony_ci		.max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT,
99662306a36Sopenharmony_ci		.packed_size = SJA1105_SIZE_VLAN_LOOKUP_DYN_CMD,
99762306a36Sopenharmony_ci		.addr = 0x2D,
99862306a36Sopenharmony_ci	},
99962306a36Sopenharmony_ci	[BLK_IDX_L2_FORWARDING] = {
100062306a36Sopenharmony_ci		.entry_packing = sja1105_l2_forwarding_entry_packing,
100162306a36Sopenharmony_ci		.cmd_packing = sja1105_l2_forwarding_cmd_packing,
100262306a36Sopenharmony_ci		.max_entry_count = SJA1105_MAX_L2_FORWARDING_COUNT,
100362306a36Sopenharmony_ci		.access = OP_WRITE,
100462306a36Sopenharmony_ci		.packed_size = SJA1105_SIZE_L2_FORWARDING_DYN_CMD,
100562306a36Sopenharmony_ci		.addr = 0x2A,
100662306a36Sopenharmony_ci	},
100762306a36Sopenharmony_ci	[BLK_IDX_MAC_CONFIG] = {
100862306a36Sopenharmony_ci		.entry_packing = sja1105pqrs_mac_config_entry_packing,
100962306a36Sopenharmony_ci		.cmd_packing = sja1105pqrs_mac_config_cmd_packing,
101062306a36Sopenharmony_ci		.max_entry_count = SJA1105_MAX_MAC_CONFIG_COUNT,
101162306a36Sopenharmony_ci		.access = (OP_READ | OP_WRITE),
101262306a36Sopenharmony_ci		.packed_size = SJA1105PQRS_SIZE_MAC_CONFIG_DYN_CMD,
101362306a36Sopenharmony_ci		.addr = 0x4B,
101462306a36Sopenharmony_ci	},
101562306a36Sopenharmony_ci	[BLK_IDX_L2_LOOKUP_PARAMS] = {
101662306a36Sopenharmony_ci		.entry_packing = sja1105pqrs_l2_lookup_params_entry_packing,
101762306a36Sopenharmony_ci		.cmd_packing = sja1105pqrs_l2_lookup_params_cmd_packing,
101862306a36Sopenharmony_ci		.max_entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT,
101962306a36Sopenharmony_ci		.access = (OP_READ | OP_WRITE),
102062306a36Sopenharmony_ci		.packed_size = SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_DYN_CMD,
102162306a36Sopenharmony_ci		.addr = 0x54,
102262306a36Sopenharmony_ci	},
102362306a36Sopenharmony_ci	[BLK_IDX_AVB_PARAMS] = {
102462306a36Sopenharmony_ci		.entry_packing = sja1105pqrs_avb_params_entry_packing,
102562306a36Sopenharmony_ci		.cmd_packing = sja1105pqrs_avb_params_cmd_packing,
102662306a36Sopenharmony_ci		.max_entry_count = SJA1105_MAX_AVB_PARAMS_COUNT,
102762306a36Sopenharmony_ci		.access = (OP_READ | OP_WRITE),
102862306a36Sopenharmony_ci		.packed_size = SJA1105PQRS_SIZE_AVB_PARAMS_DYN_CMD,
102962306a36Sopenharmony_ci		.addr = 0x8003,
103062306a36Sopenharmony_ci	},
103162306a36Sopenharmony_ci	[BLK_IDX_GENERAL_PARAMS] = {
103262306a36Sopenharmony_ci		.entry_packing = sja1105pqrs_general_params_entry_packing,
103362306a36Sopenharmony_ci		.cmd_packing = sja1105pqrs_general_params_cmd_packing,
103462306a36Sopenharmony_ci		.max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT,
103562306a36Sopenharmony_ci		.access = (OP_READ | OP_WRITE),
103662306a36Sopenharmony_ci		.packed_size = SJA1105PQRS_SIZE_GENERAL_PARAMS_DYN_CMD,
103762306a36Sopenharmony_ci		.addr = 0x3B,
103862306a36Sopenharmony_ci	},
103962306a36Sopenharmony_ci	[BLK_IDX_RETAGGING] = {
104062306a36Sopenharmony_ci		.entry_packing = sja1105_retagging_entry_packing,
104162306a36Sopenharmony_ci		.cmd_packing = sja1105_retagging_cmd_packing,
104262306a36Sopenharmony_ci		.max_entry_count = SJA1105_MAX_RETAGGING_COUNT,
104362306a36Sopenharmony_ci		.access = (OP_READ | OP_WRITE | OP_DEL),
104462306a36Sopenharmony_ci		.packed_size = SJA1105_SIZE_RETAGGING_DYN_CMD,
104562306a36Sopenharmony_ci		.addr = 0x38,
104662306a36Sopenharmony_ci	},
104762306a36Sopenharmony_ci	[BLK_IDX_CBS] = {
104862306a36Sopenharmony_ci		.entry_packing = sja1105pqrs_cbs_entry_packing,
104962306a36Sopenharmony_ci		.cmd_packing = sja1105pqrs_cbs_cmd_packing,
105062306a36Sopenharmony_ci		.max_entry_count = SJA1105PQRS_MAX_CBS_COUNT,
105162306a36Sopenharmony_ci		.access = OP_WRITE,
105262306a36Sopenharmony_ci		.packed_size = SJA1105PQRS_SIZE_CBS_DYN_CMD,
105362306a36Sopenharmony_ci		.addr = 0x32,
105462306a36Sopenharmony_ci	},
105562306a36Sopenharmony_ci};
105662306a36Sopenharmony_ci
105762306a36Sopenharmony_ci/* SJA1110: Third generation */
105862306a36Sopenharmony_ciconst struct sja1105_dynamic_table_ops sja1110_dyn_ops[BLK_IDX_MAX_DYN] = {
105962306a36Sopenharmony_ci	[BLK_IDX_VL_LOOKUP] = {
106062306a36Sopenharmony_ci		.entry_packing = sja1110_vl_lookup_entry_packing,
106162306a36Sopenharmony_ci		.cmd_packing = sja1110_vl_lookup_cmd_packing,
106262306a36Sopenharmony_ci		.access = (OP_READ | OP_WRITE | OP_VALID_ANYWAY),
106362306a36Sopenharmony_ci		.max_entry_count = SJA1110_MAX_VL_LOOKUP_COUNT,
106462306a36Sopenharmony_ci		.packed_size = SJA1105PQRS_SIZE_VL_LOOKUP_DYN_CMD,
106562306a36Sopenharmony_ci		.addr = SJA1110_SPI_ADDR(0x124),
106662306a36Sopenharmony_ci	},
106762306a36Sopenharmony_ci	[BLK_IDX_VL_POLICING] = {
106862306a36Sopenharmony_ci		.entry_packing = sja1110_vl_policing_entry_packing,
106962306a36Sopenharmony_ci		.cmd_packing = sja1110_vl_policing_cmd_packing,
107062306a36Sopenharmony_ci		.access = (OP_READ | OP_WRITE | OP_VALID_ANYWAY),
107162306a36Sopenharmony_ci		.max_entry_count = SJA1110_MAX_VL_POLICING_COUNT,
107262306a36Sopenharmony_ci		.packed_size = SJA1110_SIZE_VL_POLICING_DYN_CMD,
107362306a36Sopenharmony_ci		.addr = SJA1110_SPI_ADDR(0x310),
107462306a36Sopenharmony_ci	},
107562306a36Sopenharmony_ci	[BLK_IDX_L2_LOOKUP] = {
107662306a36Sopenharmony_ci		.entry_packing = sja1110_dyn_l2_lookup_entry_packing,
107762306a36Sopenharmony_ci		.cmd_packing = sja1110_l2_lookup_cmd_packing,
107862306a36Sopenharmony_ci		.access = (OP_READ | OP_WRITE | OP_DEL | OP_SEARCH),
107962306a36Sopenharmony_ci		.max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT,
108062306a36Sopenharmony_ci		.packed_size = SJA1110_SIZE_L2_LOOKUP_DYN_CMD,
108162306a36Sopenharmony_ci		.addr = SJA1110_SPI_ADDR(0x8c),
108262306a36Sopenharmony_ci	},
108362306a36Sopenharmony_ci	[BLK_IDX_VLAN_LOOKUP] = {
108462306a36Sopenharmony_ci		.entry_packing = sja1110_vlan_lookup_entry_packing,
108562306a36Sopenharmony_ci		.cmd_packing = sja1110_vlan_lookup_cmd_packing,
108662306a36Sopenharmony_ci		.access = (OP_READ | OP_WRITE | OP_DEL),
108762306a36Sopenharmony_ci		.max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT,
108862306a36Sopenharmony_ci		.packed_size = SJA1110_SIZE_VLAN_LOOKUP_DYN_CMD,
108962306a36Sopenharmony_ci		.addr = SJA1110_SPI_ADDR(0xb4),
109062306a36Sopenharmony_ci	},
109162306a36Sopenharmony_ci	[BLK_IDX_L2_FORWARDING] = {
109262306a36Sopenharmony_ci		.entry_packing = sja1110_l2_forwarding_entry_packing,
109362306a36Sopenharmony_ci		.cmd_packing = sja1110_l2_forwarding_cmd_packing,
109462306a36Sopenharmony_ci		.max_entry_count = SJA1110_MAX_L2_FORWARDING_COUNT,
109562306a36Sopenharmony_ci		.access = (OP_READ | OP_WRITE | OP_VALID_ANYWAY),
109662306a36Sopenharmony_ci		.packed_size = SJA1105_SIZE_L2_FORWARDING_DYN_CMD,
109762306a36Sopenharmony_ci		.addr = SJA1110_SPI_ADDR(0xa8),
109862306a36Sopenharmony_ci	},
109962306a36Sopenharmony_ci	[BLK_IDX_MAC_CONFIG] = {
110062306a36Sopenharmony_ci		.entry_packing = sja1110_mac_config_entry_packing,
110162306a36Sopenharmony_ci		.cmd_packing = sja1110_mac_config_cmd_packing,
110262306a36Sopenharmony_ci		.max_entry_count = SJA1110_MAX_MAC_CONFIG_COUNT,
110362306a36Sopenharmony_ci		.access = (OP_READ | OP_WRITE | OP_VALID_ANYWAY),
110462306a36Sopenharmony_ci		.packed_size = SJA1105PQRS_SIZE_MAC_CONFIG_DYN_CMD,
110562306a36Sopenharmony_ci		.addr = SJA1110_SPI_ADDR(0x134),
110662306a36Sopenharmony_ci	},
110762306a36Sopenharmony_ci	[BLK_IDX_L2_LOOKUP_PARAMS] = {
110862306a36Sopenharmony_ci		.entry_packing = sja1110_l2_lookup_params_entry_packing,
110962306a36Sopenharmony_ci		.cmd_packing = sja1110_l2_lookup_params_cmd_packing,
111062306a36Sopenharmony_ci		.max_entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT,
111162306a36Sopenharmony_ci		.access = (OP_READ | OP_WRITE | OP_VALID_ANYWAY),
111262306a36Sopenharmony_ci		.packed_size = SJA1110_SIZE_L2_LOOKUP_PARAMS_DYN_CMD,
111362306a36Sopenharmony_ci		.addr = SJA1110_SPI_ADDR(0x158),
111462306a36Sopenharmony_ci	},
111562306a36Sopenharmony_ci	[BLK_IDX_AVB_PARAMS] = {
111662306a36Sopenharmony_ci		.entry_packing = sja1105pqrs_avb_params_entry_packing,
111762306a36Sopenharmony_ci		.cmd_packing = sja1105pqrs_avb_params_cmd_packing,
111862306a36Sopenharmony_ci		.max_entry_count = SJA1105_MAX_AVB_PARAMS_COUNT,
111962306a36Sopenharmony_ci		.access = (OP_READ | OP_WRITE | OP_VALID_ANYWAY),
112062306a36Sopenharmony_ci		.packed_size = SJA1105PQRS_SIZE_AVB_PARAMS_DYN_CMD,
112162306a36Sopenharmony_ci		.addr = SJA1110_SPI_ADDR(0x2000C),
112262306a36Sopenharmony_ci	},
112362306a36Sopenharmony_ci	[BLK_IDX_GENERAL_PARAMS] = {
112462306a36Sopenharmony_ci		.entry_packing = sja1110_general_params_entry_packing,
112562306a36Sopenharmony_ci		.cmd_packing = sja1110_general_params_cmd_packing,
112662306a36Sopenharmony_ci		.max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT,
112762306a36Sopenharmony_ci		.access = (OP_READ | OP_WRITE | OP_VALID_ANYWAY),
112862306a36Sopenharmony_ci		.packed_size = SJA1110_SIZE_GENERAL_PARAMS_DYN_CMD,
112962306a36Sopenharmony_ci		.addr = SJA1110_SPI_ADDR(0xe8),
113062306a36Sopenharmony_ci	},
113162306a36Sopenharmony_ci	[BLK_IDX_RETAGGING] = {
113262306a36Sopenharmony_ci		.entry_packing = sja1110_retagging_entry_packing,
113362306a36Sopenharmony_ci		.cmd_packing = sja1110_retagging_cmd_packing,
113462306a36Sopenharmony_ci		.max_entry_count = SJA1105_MAX_RETAGGING_COUNT,
113562306a36Sopenharmony_ci		.access = (OP_READ | OP_WRITE | OP_DEL),
113662306a36Sopenharmony_ci		.packed_size = SJA1105_SIZE_RETAGGING_DYN_CMD,
113762306a36Sopenharmony_ci		.addr = SJA1110_SPI_ADDR(0xdc),
113862306a36Sopenharmony_ci	},
113962306a36Sopenharmony_ci	[BLK_IDX_CBS] = {
114062306a36Sopenharmony_ci		.entry_packing = sja1110_cbs_entry_packing,
114162306a36Sopenharmony_ci		.cmd_packing = sja1110_cbs_cmd_packing,
114262306a36Sopenharmony_ci		.max_entry_count = SJA1110_MAX_CBS_COUNT,
114362306a36Sopenharmony_ci		.access = (OP_READ | OP_WRITE | OP_VALID_ANYWAY),
114462306a36Sopenharmony_ci		.packed_size = SJA1105PQRS_SIZE_CBS_DYN_CMD,
114562306a36Sopenharmony_ci		.addr = SJA1110_SPI_ADDR(0xc4),
114662306a36Sopenharmony_ci	},
114762306a36Sopenharmony_ci	[BLK_IDX_XMII_PARAMS] = {
114862306a36Sopenharmony_ci		.entry_packing = sja1110_xmii_params_entry_packing,
114962306a36Sopenharmony_ci		.cmd_packing = sja1110_dummy_cmd_packing,
115062306a36Sopenharmony_ci		.max_entry_count = SJA1105_MAX_XMII_PARAMS_COUNT,
115162306a36Sopenharmony_ci		.access = (OP_READ | OP_VALID_ANYWAY),
115262306a36Sopenharmony_ci		.packed_size = SJA1110_SIZE_XMII_PARAMS_DYN_CMD,
115362306a36Sopenharmony_ci		.addr = SJA1110_SPI_ADDR(0x3c),
115462306a36Sopenharmony_ci	},
115562306a36Sopenharmony_ci	[BLK_IDX_L2_POLICING] = {
115662306a36Sopenharmony_ci		.entry_packing = sja1110_l2_policing_entry_packing,
115762306a36Sopenharmony_ci		.cmd_packing = sja1110_l2_policing_cmd_packing,
115862306a36Sopenharmony_ci		.max_entry_count = SJA1110_MAX_L2_POLICING_COUNT,
115962306a36Sopenharmony_ci		.access = (OP_READ | OP_WRITE | OP_VALID_ANYWAY),
116062306a36Sopenharmony_ci		.packed_size = SJA1110_SIZE_L2_POLICING_DYN_CMD,
116162306a36Sopenharmony_ci		.addr = SJA1110_SPI_ADDR(0x2fc),
116262306a36Sopenharmony_ci	},
116362306a36Sopenharmony_ci	[BLK_IDX_L2_FORWARDING_PARAMS] = {
116462306a36Sopenharmony_ci		.entry_packing = sja1110_l2_forwarding_params_entry_packing,
116562306a36Sopenharmony_ci		.cmd_packing = sja1110_dummy_cmd_packing,
116662306a36Sopenharmony_ci		.max_entry_count = SJA1105_MAX_L2_FORWARDING_PARAMS_COUNT,
116762306a36Sopenharmony_ci		.access = (OP_READ | OP_VALID_ANYWAY),
116862306a36Sopenharmony_ci		.packed_size = SJA1110_SIZE_L2_FORWARDING_PARAMS_DYN_CMD,
116962306a36Sopenharmony_ci		.addr = SJA1110_SPI_ADDR(0x20000),
117062306a36Sopenharmony_ci	},
117162306a36Sopenharmony_ci};
117262306a36Sopenharmony_ci
117362306a36Sopenharmony_ci#define SJA1105_DYNAMIC_CONFIG_SLEEP_US		10
117462306a36Sopenharmony_ci#define SJA1105_DYNAMIC_CONFIG_TIMEOUT_US	100000
117562306a36Sopenharmony_ci
117662306a36Sopenharmony_cistatic int
117762306a36Sopenharmony_cisja1105_dynamic_config_poll_valid(struct sja1105_private *priv,
117862306a36Sopenharmony_ci				  const struct sja1105_dynamic_table_ops *ops,
117962306a36Sopenharmony_ci				  void *entry, bool check_valident,
118062306a36Sopenharmony_ci				  bool check_errors)
118162306a36Sopenharmony_ci{
118262306a36Sopenharmony_ci	u8 packed_buf[SJA1105_MAX_DYN_CMD_SIZE] = {};
118362306a36Sopenharmony_ci	struct sja1105_dyn_cmd cmd = {};
118462306a36Sopenharmony_ci	int rc;
118562306a36Sopenharmony_ci
118662306a36Sopenharmony_ci	/* Read back the whole entry + command structure. */
118762306a36Sopenharmony_ci	rc = sja1105_xfer_buf(priv, SPI_READ, ops->addr, packed_buf,
118862306a36Sopenharmony_ci			      ops->packed_size);
118962306a36Sopenharmony_ci	if (rc)
119062306a36Sopenharmony_ci		return rc;
119162306a36Sopenharmony_ci
119262306a36Sopenharmony_ci	/* Unpack the command structure, and return it to the caller in case it
119362306a36Sopenharmony_ci	 * needs to perform further checks on it (VALIDENT).
119462306a36Sopenharmony_ci	 */
119562306a36Sopenharmony_ci	ops->cmd_packing(packed_buf, &cmd, UNPACK);
119662306a36Sopenharmony_ci
119762306a36Sopenharmony_ci	/* Hardware hasn't cleared VALID => still working on it */
119862306a36Sopenharmony_ci	if (cmd.valid)
119962306a36Sopenharmony_ci		return -EAGAIN;
120062306a36Sopenharmony_ci
120162306a36Sopenharmony_ci	if (check_valident && !cmd.valident && !(ops->access & OP_VALID_ANYWAY))
120262306a36Sopenharmony_ci		return -ENOENT;
120362306a36Sopenharmony_ci
120462306a36Sopenharmony_ci	if (check_errors && cmd.errors)
120562306a36Sopenharmony_ci		return -EINVAL;
120662306a36Sopenharmony_ci
120762306a36Sopenharmony_ci	/* Don't dereference possibly NULL pointer - maybe caller
120862306a36Sopenharmony_ci	 * only wanted to see whether the entry existed or not.
120962306a36Sopenharmony_ci	 */
121062306a36Sopenharmony_ci	if (entry)
121162306a36Sopenharmony_ci		ops->entry_packing(packed_buf, entry, UNPACK);
121262306a36Sopenharmony_ci
121362306a36Sopenharmony_ci	return 0;
121462306a36Sopenharmony_ci}
121562306a36Sopenharmony_ci
121662306a36Sopenharmony_ci/* Poll the dynamic config entry's control area until the hardware has
121762306a36Sopenharmony_ci * cleared the VALID bit, which means we have confirmation that it has
121862306a36Sopenharmony_ci * finished processing the command.
121962306a36Sopenharmony_ci */
122062306a36Sopenharmony_cistatic int
122162306a36Sopenharmony_cisja1105_dynamic_config_wait_complete(struct sja1105_private *priv,
122262306a36Sopenharmony_ci				     const struct sja1105_dynamic_table_ops *ops,
122362306a36Sopenharmony_ci				     void *entry, bool check_valident,
122462306a36Sopenharmony_ci				     bool check_errors)
122562306a36Sopenharmony_ci{
122662306a36Sopenharmony_ci	int err, rc;
122762306a36Sopenharmony_ci
122862306a36Sopenharmony_ci	err = read_poll_timeout(sja1105_dynamic_config_poll_valid,
122962306a36Sopenharmony_ci				rc, rc != -EAGAIN,
123062306a36Sopenharmony_ci				SJA1105_DYNAMIC_CONFIG_SLEEP_US,
123162306a36Sopenharmony_ci				SJA1105_DYNAMIC_CONFIG_TIMEOUT_US,
123262306a36Sopenharmony_ci				false, priv, ops, entry, check_valident,
123362306a36Sopenharmony_ci				check_errors);
123462306a36Sopenharmony_ci	return err < 0 ? err : rc;
123562306a36Sopenharmony_ci}
123662306a36Sopenharmony_ci
123762306a36Sopenharmony_ci/* Provides read access to the settings through the dynamic interface
123862306a36Sopenharmony_ci * of the switch.
123962306a36Sopenharmony_ci * @blk_idx	is used as key to select from the sja1105_dynamic_table_ops.
124062306a36Sopenharmony_ci *		The selection is limited by the hardware in respect to which
124162306a36Sopenharmony_ci *		configuration blocks can be read through the dynamic interface.
124262306a36Sopenharmony_ci * @index	is used to retrieve a particular table entry. If negative,
124362306a36Sopenharmony_ci *		(and if the @blk_idx supports the searching operation) a search
124462306a36Sopenharmony_ci *		is performed by the @entry parameter.
124562306a36Sopenharmony_ci * @entry	Type-casted to an unpacked structure that holds a table entry
124662306a36Sopenharmony_ci *		of the type specified in @blk_idx.
124762306a36Sopenharmony_ci *		Usually an output argument. If @index is negative, then this
124862306a36Sopenharmony_ci *		argument is used as input/output: it should be pre-populated
124962306a36Sopenharmony_ci *		with the element to search for. Entries which support the
125062306a36Sopenharmony_ci *		search operation will have an "index" field (not the @index
125162306a36Sopenharmony_ci *		argument to this function) and that is where the found index
125262306a36Sopenharmony_ci *		will be returned (or left unmodified - thus negative - if not
125362306a36Sopenharmony_ci *		found).
125462306a36Sopenharmony_ci */
125562306a36Sopenharmony_ciint sja1105_dynamic_config_read(struct sja1105_private *priv,
125662306a36Sopenharmony_ci				enum sja1105_blk_idx blk_idx,
125762306a36Sopenharmony_ci				int index, void *entry)
125862306a36Sopenharmony_ci{
125962306a36Sopenharmony_ci	const struct sja1105_dynamic_table_ops *ops;
126062306a36Sopenharmony_ci	struct sja1105_dyn_cmd cmd = {0};
126162306a36Sopenharmony_ci	/* SPI payload buffer */
126262306a36Sopenharmony_ci	u8 packed_buf[SJA1105_MAX_DYN_CMD_SIZE] = {0};
126362306a36Sopenharmony_ci	int rc;
126462306a36Sopenharmony_ci
126562306a36Sopenharmony_ci	if (blk_idx >= BLK_IDX_MAX_DYN)
126662306a36Sopenharmony_ci		return -ERANGE;
126762306a36Sopenharmony_ci
126862306a36Sopenharmony_ci	ops = &priv->info->dyn_ops[blk_idx];
126962306a36Sopenharmony_ci
127062306a36Sopenharmony_ci	if (index >= 0 && index >= ops->max_entry_count)
127162306a36Sopenharmony_ci		return -ERANGE;
127262306a36Sopenharmony_ci	if (index < 0 && !(ops->access & OP_SEARCH))
127362306a36Sopenharmony_ci		return -EOPNOTSUPP;
127462306a36Sopenharmony_ci	if (!(ops->access & OP_READ))
127562306a36Sopenharmony_ci		return -EOPNOTSUPP;
127662306a36Sopenharmony_ci	if (ops->packed_size > SJA1105_MAX_DYN_CMD_SIZE)
127762306a36Sopenharmony_ci		return -ERANGE;
127862306a36Sopenharmony_ci	if (!ops->cmd_packing)
127962306a36Sopenharmony_ci		return -EOPNOTSUPP;
128062306a36Sopenharmony_ci	if (!ops->entry_packing)
128162306a36Sopenharmony_ci		return -EOPNOTSUPP;
128262306a36Sopenharmony_ci
128362306a36Sopenharmony_ci	cmd.valid = true; /* Trigger action on table entry */
128462306a36Sopenharmony_ci	cmd.rdwrset = SPI_READ; /* Action is read */
128562306a36Sopenharmony_ci	if (index < 0) {
128662306a36Sopenharmony_ci		/* Avoid copying a signed negative number to an u64 */
128762306a36Sopenharmony_ci		cmd.index = 0;
128862306a36Sopenharmony_ci		cmd.search = true;
128962306a36Sopenharmony_ci	} else {
129062306a36Sopenharmony_ci		cmd.index = index;
129162306a36Sopenharmony_ci		cmd.search = false;
129262306a36Sopenharmony_ci	}
129362306a36Sopenharmony_ci	cmd.valident = true;
129462306a36Sopenharmony_ci	ops->cmd_packing(packed_buf, &cmd, PACK);
129562306a36Sopenharmony_ci
129662306a36Sopenharmony_ci	if (cmd.search)
129762306a36Sopenharmony_ci		ops->entry_packing(packed_buf, entry, PACK);
129862306a36Sopenharmony_ci
129962306a36Sopenharmony_ci	/* Send SPI write operation: read config table entry */
130062306a36Sopenharmony_ci	mutex_lock(&priv->dynamic_config_lock);
130162306a36Sopenharmony_ci	rc = sja1105_xfer_buf(priv, SPI_WRITE, ops->addr, packed_buf,
130262306a36Sopenharmony_ci			      ops->packed_size);
130362306a36Sopenharmony_ci	if (rc < 0)
130462306a36Sopenharmony_ci		goto out;
130562306a36Sopenharmony_ci
130662306a36Sopenharmony_ci	rc = sja1105_dynamic_config_wait_complete(priv, ops, entry, true, false);
130762306a36Sopenharmony_ciout:
130862306a36Sopenharmony_ci	mutex_unlock(&priv->dynamic_config_lock);
130962306a36Sopenharmony_ci
131062306a36Sopenharmony_ci	return rc;
131162306a36Sopenharmony_ci}
131262306a36Sopenharmony_ci
131362306a36Sopenharmony_ciint sja1105_dynamic_config_write(struct sja1105_private *priv,
131462306a36Sopenharmony_ci				 enum sja1105_blk_idx blk_idx,
131562306a36Sopenharmony_ci				 int index, void *entry, bool keep)
131662306a36Sopenharmony_ci{
131762306a36Sopenharmony_ci	const struct sja1105_dynamic_table_ops *ops;
131862306a36Sopenharmony_ci	struct sja1105_dyn_cmd cmd = {0};
131962306a36Sopenharmony_ci	/* SPI payload buffer */
132062306a36Sopenharmony_ci	u8 packed_buf[SJA1105_MAX_DYN_CMD_SIZE] = {0};
132162306a36Sopenharmony_ci	int rc;
132262306a36Sopenharmony_ci
132362306a36Sopenharmony_ci	if (blk_idx >= BLK_IDX_MAX_DYN)
132462306a36Sopenharmony_ci		return -ERANGE;
132562306a36Sopenharmony_ci
132662306a36Sopenharmony_ci	ops = &priv->info->dyn_ops[blk_idx];
132762306a36Sopenharmony_ci
132862306a36Sopenharmony_ci	if (index >= ops->max_entry_count)
132962306a36Sopenharmony_ci		return -ERANGE;
133062306a36Sopenharmony_ci	if (index < 0)
133162306a36Sopenharmony_ci		return -ERANGE;
133262306a36Sopenharmony_ci	if (!(ops->access & OP_WRITE))
133362306a36Sopenharmony_ci		return -EOPNOTSUPP;
133462306a36Sopenharmony_ci	if (!keep && !(ops->access & OP_DEL))
133562306a36Sopenharmony_ci		return -EOPNOTSUPP;
133662306a36Sopenharmony_ci	if (ops->packed_size > SJA1105_MAX_DYN_CMD_SIZE)
133762306a36Sopenharmony_ci		return -ERANGE;
133862306a36Sopenharmony_ci
133962306a36Sopenharmony_ci	cmd.valident = keep; /* If false, deletes entry */
134062306a36Sopenharmony_ci	cmd.valid = true; /* Trigger action on table entry */
134162306a36Sopenharmony_ci	cmd.rdwrset = SPI_WRITE; /* Action is write */
134262306a36Sopenharmony_ci	cmd.index = index;
134362306a36Sopenharmony_ci
134462306a36Sopenharmony_ci	if (!ops->cmd_packing)
134562306a36Sopenharmony_ci		return -EOPNOTSUPP;
134662306a36Sopenharmony_ci	ops->cmd_packing(packed_buf, &cmd, PACK);
134762306a36Sopenharmony_ci
134862306a36Sopenharmony_ci	if (!ops->entry_packing)
134962306a36Sopenharmony_ci		return -EOPNOTSUPP;
135062306a36Sopenharmony_ci	/* Don't dereference potentially NULL pointer if just
135162306a36Sopenharmony_ci	 * deleting a table entry is what was requested. For cases
135262306a36Sopenharmony_ci	 * where 'index' field is physically part of entry structure,
135362306a36Sopenharmony_ci	 * and needed here, we deal with that in the cmd_packing callback.
135462306a36Sopenharmony_ci	 */
135562306a36Sopenharmony_ci	if (keep)
135662306a36Sopenharmony_ci		ops->entry_packing(packed_buf, entry, PACK);
135762306a36Sopenharmony_ci
135862306a36Sopenharmony_ci	/* Send SPI write operation: read config table entry */
135962306a36Sopenharmony_ci	mutex_lock(&priv->dynamic_config_lock);
136062306a36Sopenharmony_ci	rc = sja1105_xfer_buf(priv, SPI_WRITE, ops->addr, packed_buf,
136162306a36Sopenharmony_ci			      ops->packed_size);
136262306a36Sopenharmony_ci	if (rc < 0)
136362306a36Sopenharmony_ci		goto out;
136462306a36Sopenharmony_ci
136562306a36Sopenharmony_ci	rc = sja1105_dynamic_config_wait_complete(priv, ops, NULL, false, true);
136662306a36Sopenharmony_ciout:
136762306a36Sopenharmony_ci	mutex_unlock(&priv->dynamic_config_lock);
136862306a36Sopenharmony_ci
136962306a36Sopenharmony_ci	return rc;
137062306a36Sopenharmony_ci}
137162306a36Sopenharmony_ci
137262306a36Sopenharmony_cistatic u8 sja1105_crc8_add(u8 crc, u8 byte, u8 poly)
137362306a36Sopenharmony_ci{
137462306a36Sopenharmony_ci	int i;
137562306a36Sopenharmony_ci
137662306a36Sopenharmony_ci	for (i = 0; i < 8; i++) {
137762306a36Sopenharmony_ci		if ((crc ^ byte) & (1 << 7)) {
137862306a36Sopenharmony_ci			crc <<= 1;
137962306a36Sopenharmony_ci			crc ^= poly;
138062306a36Sopenharmony_ci		} else {
138162306a36Sopenharmony_ci			crc <<= 1;
138262306a36Sopenharmony_ci		}
138362306a36Sopenharmony_ci		byte <<= 1;
138462306a36Sopenharmony_ci	}
138562306a36Sopenharmony_ci	return crc;
138662306a36Sopenharmony_ci}
138762306a36Sopenharmony_ci
138862306a36Sopenharmony_ci/* CRC8 algorithm with non-reversed input, non-reversed output,
138962306a36Sopenharmony_ci * no input xor and no output xor. Code customized for receiving
139062306a36Sopenharmony_ci * the SJA1105 E/T FDB keys (vlanid, macaddr) as input. CRC polynomial
139162306a36Sopenharmony_ci * is also received as argument in the Koopman notation that the switch
139262306a36Sopenharmony_ci * hardware stores it in.
139362306a36Sopenharmony_ci */
139462306a36Sopenharmony_ciu8 sja1105et_fdb_hash(struct sja1105_private *priv, const u8 *addr, u16 vid)
139562306a36Sopenharmony_ci{
139662306a36Sopenharmony_ci	struct sja1105_l2_lookup_params_entry *l2_lookup_params =
139762306a36Sopenharmony_ci		priv->static_config.tables[BLK_IDX_L2_LOOKUP_PARAMS].entries;
139862306a36Sopenharmony_ci	u64 input, poly_koopman = l2_lookup_params->poly;
139962306a36Sopenharmony_ci	/* Convert polynomial from Koopman to 'normal' notation */
140062306a36Sopenharmony_ci	u8 poly = (u8)(1 + (poly_koopman << 1));
140162306a36Sopenharmony_ci	u8 crc = 0; /* seed */
140262306a36Sopenharmony_ci	int i;
140362306a36Sopenharmony_ci
140462306a36Sopenharmony_ci	input = ((u64)vid << 48) | ether_addr_to_u64(addr);
140562306a36Sopenharmony_ci
140662306a36Sopenharmony_ci	/* Mask the eight bytes starting from MSB one at a time */
140762306a36Sopenharmony_ci	for (i = 56; i >= 0; i -= 8) {
140862306a36Sopenharmony_ci		u8 byte = (input & (0xffull << i)) >> i;
140962306a36Sopenharmony_ci
141062306a36Sopenharmony_ci		crc = sja1105_crc8_add(crc, byte, poly);
141162306a36Sopenharmony_ci	}
141262306a36Sopenharmony_ci	return crc;
141362306a36Sopenharmony_ci}
1414