Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
   1// SPDX-License-Identifier: GPL-2.0
   2/* Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com>
   3 */
   4#include "sja1105.h"
   5
   6/* In the dynamic configuration interface, the switch exposes a register-like
   7 * view of some of the static configuration tables.
   8 * Many times the field organization of the dynamic tables is abbreviated (not
   9 * all fields are dynamically reconfigurable) and different from the static
  10 * ones, but the key reason for having it is that we can spare a switch reset
  11 * for settings that can be changed dynamically.
  12 *
  13 * This file creates a per-switch-family abstraction called
  14 * struct sja1105_dynamic_table_ops and two operations that work with it:
  15 * - sja1105_dynamic_config_write
  16 * - sja1105_dynamic_config_read
  17 *
  18 * Compared to the struct sja1105_table_ops from sja1105_static_config.c,
  19 * the dynamic accessors work with a compound buffer:
  20 *
  21 * packed_buf
  22 *
  23 * |
  24 * V
  25 * +-----------------------------------------+------------------+
  26 * |              ENTRY BUFFER               |  COMMAND BUFFER  |
  27 * +-----------------------------------------+------------------+
  28 *
  29 * <----------------------- packed_size ------------------------>
  30 *
  31 * The ENTRY BUFFER may or may not have the same layout, or size, as its static
  32 * configuration table entry counterpart. When it does, the same packing
  33 * function is reused (bar exceptional cases - see
  34 * sja1105pqrs_dyn_l2_lookup_entry_packing).
  35 *
  36 * The reason for the COMMAND BUFFER being at the end is to be able to send
  37 * a dynamic write command through a single SPI burst. By the time the switch
  38 * reacts to the command, the ENTRY BUFFER is already populated with the data
  39 * sent by the core.
  40 *
  41 * The COMMAND BUFFER is always SJA1105_SIZE_DYN_CMD bytes (one 32-bit word) in
  42 * size.
  43 *
  44 * Sometimes the ENTRY BUFFER does not really exist (when the number of fields
  45 * that can be reconfigured is small), then the switch repurposes some of the
  46 * unused 32 bits of the COMMAND BUFFER to hold ENTRY data.
  47 *
  48 * The key members of struct sja1105_dynamic_table_ops are:
  49 * - .entry_packing: A function that deals with packing an ENTRY structure
  50 *		     into an SPI buffer, or retrieving an ENTRY structure
  51 *		     from one.
  52 *		     The @packed_buf pointer it's given does always point to
  53 *		     the ENTRY portion of the buffer.
  54 * - .cmd_packing: A function that deals with packing/unpacking the COMMAND
  55 *		   structure to/from the SPI buffer.
  56 *		   It is given the same @packed_buf pointer as .entry_packing,
  57 *		   so most of the time, the @packed_buf points *behind* the
  58 *		   COMMAND offset inside the buffer.
  59 *		   To access the COMMAND portion of the buffer, the function
  60 *		   knows its correct offset.
  61 *		   Giving both functions the same pointer is handy because in
  62 *		   extreme cases (see sja1105pqrs_dyn_l2_lookup_entry_packing)
  63 *		   the .entry_packing is able to jump to the COMMAND portion,
  64 *		   or vice-versa (sja1105pqrs_l2_lookup_cmd_packing).
  65 * - .access: A bitmap of:
  66 *	OP_READ: Set if the hardware manual marks the ENTRY portion of the
  67 *		 dynamic configuration table buffer as R (readable) after
  68 *		 an SPI read command (the switch will populate the buffer).
  69 *	OP_WRITE: Set if the manual marks the ENTRY portion of the dynamic
  70 *		  table buffer as W (writable) after an SPI write command
  71 *		  (the switch will read the fields provided in the buffer).
  72 *	OP_DEL: Set if the manual says the VALIDENT bit is supported in the
  73 *		COMMAND portion of this dynamic config buffer (i.e. the
  74 *		specified entry can be invalidated through a SPI write
  75 *		command).
  76 *	OP_SEARCH: Set if the manual says that the index of an entry can
  77 *		   be retrieved in the COMMAND portion of the buffer based
  78 *		   on its ENTRY portion, as a result of a SPI write command.
  79 *		   Only the TCAM-based FDB table on SJA1105 P/Q/R/S supports
  80 *		   this.
  81 * - .max_entry_count: The number of entries, counting from zero, that can be
  82 *		       reconfigured through the dynamic interface. If a static
  83 *		       table can be reconfigured at all dynamically, this
  84 *		       number always matches the maximum number of supported
  85 *		       static entries.
  86 * - .packed_size: The length in bytes of the compound ENTRY + COMMAND BUFFER.
  87 *		   Note that sometimes the compound buffer may contain holes in
  88 *		   it (see sja1105_vlan_lookup_cmd_packing). The @packed_buf is
  89 *		   contiguous however, so @packed_size includes any unused
  90 *		   bytes.
  91 * - .addr: The base SPI address at which the buffer must be written to the
  92 *	    switch's memory. When looking at the hardware manual, this must
  93 *	    always match the lowest documented address for the ENTRY, and not
  94 *	    that of the COMMAND, since the other 32-bit words will follow along
  95 *	    at the correct addresses.
  96 */
  97
  98#define SJA1105_SIZE_DYN_CMD					4
  99
 100#define SJA1105ET_SJA1105_SIZE_VL_LOOKUP_DYN_CMD		\
 101	SJA1105_SIZE_DYN_CMD
 102
 103#define SJA1105PQRS_SJA1105_SIZE_VL_LOOKUP_DYN_CMD		\
 104	(SJA1105_SIZE_DYN_CMD + SJA1105_SIZE_VL_LOOKUP_ENTRY)
 105
 106#define SJA1105ET_SIZE_MAC_CONFIG_DYN_ENTRY			\
 107	SJA1105_SIZE_DYN_CMD
 108
 109#define SJA1105ET_SIZE_L2_LOOKUP_DYN_CMD			\
 110	(SJA1105_SIZE_DYN_CMD + SJA1105ET_SIZE_L2_LOOKUP_ENTRY)
 111
 112#define SJA1105PQRS_SIZE_L2_LOOKUP_DYN_CMD			\
 113	(SJA1105_SIZE_DYN_CMD + SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY)
 114
 115#define SJA1105_SIZE_VLAN_LOOKUP_DYN_CMD			\
 116	(SJA1105_SIZE_DYN_CMD + 4 + SJA1105_SIZE_VLAN_LOOKUP_ENTRY)
 117
 118#define SJA1105_SIZE_L2_FORWARDING_DYN_CMD			\
 119	(SJA1105_SIZE_DYN_CMD + SJA1105_SIZE_L2_FORWARDING_ENTRY)
 120
 121#define SJA1105ET_SIZE_MAC_CONFIG_DYN_CMD			\
 122	(SJA1105_SIZE_DYN_CMD + SJA1105ET_SIZE_MAC_CONFIG_DYN_ENTRY)
 123
 124#define SJA1105PQRS_SIZE_MAC_CONFIG_DYN_CMD			\
 125	(SJA1105_SIZE_DYN_CMD + SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY)
 126
 127#define SJA1105ET_SIZE_L2_LOOKUP_PARAMS_DYN_CMD			\
 128	SJA1105_SIZE_DYN_CMD
 129
 130#define SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_DYN_CMD		\
 131	(SJA1105_SIZE_DYN_CMD + SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_ENTRY)
 132
 133#define SJA1105ET_SIZE_GENERAL_PARAMS_DYN_CMD			\
 134	SJA1105_SIZE_DYN_CMD
 135
 136#define SJA1105PQRS_SIZE_GENERAL_PARAMS_DYN_CMD			\
 137	(SJA1105_SIZE_DYN_CMD + SJA1105PQRS_SIZE_GENERAL_PARAMS_ENTRY)
 138
 139#define SJA1105PQRS_SIZE_AVB_PARAMS_DYN_CMD			\
 140	(SJA1105_SIZE_DYN_CMD + SJA1105PQRS_SIZE_AVB_PARAMS_ENTRY)
 141
 142#define SJA1105_SIZE_RETAGGING_DYN_CMD				\
 143	(SJA1105_SIZE_DYN_CMD + SJA1105_SIZE_RETAGGING_ENTRY)
 144
 145#define SJA1105ET_SIZE_CBS_DYN_CMD				\
 146	(SJA1105_SIZE_DYN_CMD + SJA1105ET_SIZE_CBS_ENTRY)
 147
 148#define SJA1105PQRS_SIZE_CBS_DYN_CMD				\
 149	(SJA1105_SIZE_DYN_CMD + SJA1105PQRS_SIZE_CBS_ENTRY)
 150
 151#define SJA1105_MAX_DYN_CMD_SIZE				\
 152	SJA1105PQRS_SIZE_GENERAL_PARAMS_DYN_CMD
 153
 154struct sja1105_dyn_cmd {
 155	bool search;
 156	u64 valid;
 157	u64 rdwrset;
 158	u64 errors;
 159	u64 valident;
 160	u64 index;
 161};
 162
 163enum sja1105_hostcmd {
 164	SJA1105_HOSTCMD_SEARCH = 1,
 165	SJA1105_HOSTCMD_READ = 2,
 166	SJA1105_HOSTCMD_WRITE = 3,
 167	SJA1105_HOSTCMD_INVALIDATE = 4,
 168};
 169
 170static void
 171sja1105_vl_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
 172			      enum packing_op op)
 173{
 174	const int size = SJA1105_SIZE_DYN_CMD;
 175
 176	sja1105_packing(buf, &cmd->valid,   31, 31, size, op);
 177	sja1105_packing(buf, &cmd->errors,  30, 30, size, op);
 178	sja1105_packing(buf, &cmd->rdwrset, 29, 29, size, op);
 179	sja1105_packing(buf, &cmd->index,    9,  0, size, op);
 180}
 181
 182static size_t sja1105et_vl_lookup_entry_packing(void *buf, void *entry_ptr,
 183						enum packing_op op)
 184{
 185	struct sja1105_vl_lookup_entry *entry = entry_ptr;
 186	const int size = SJA1105ET_SJA1105_SIZE_VL_LOOKUP_DYN_CMD;
 187
 188	sja1105_packing(buf, &entry->egrmirr,  21, 17, size, op);
 189	sja1105_packing(buf, &entry->ingrmirr, 16, 16, size, op);
 190	return size;
 191}
 192
 193static void
 194sja1105pqrs_l2_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
 195				  enum packing_op op)
 196{
 197	u8 *p = buf + SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY;
 198	const int size = SJA1105_SIZE_DYN_CMD;
 199	u64 hostcmd;
 200
 201	sja1105_packing(p, &cmd->valid,    31, 31, size, op);
 202	sja1105_packing(p, &cmd->rdwrset,  30, 30, size, op);
 203	sja1105_packing(p, &cmd->errors,   29, 29, size, op);
 204	sja1105_packing(p, &cmd->valident, 27, 27, size, op);
 205
 206	/* VALIDENT is supposed to indicate "keep or not", but in SJA1105 E/T,
 207	 * using it to delete a management route was unsupported. UM10944
 208	 * said about it:
 209	 *
 210	 *   In case of a write access with the MGMTROUTE flag set,
 211	 *   the flag will be ignored. It will always be found cleared
 212	 *   for read accesses with the MGMTROUTE flag set.
 213	 *
 214	 * SJA1105 P/Q/R/S keeps the same behavior w.r.t. VALIDENT, but there
 215	 * is now another flag called HOSTCMD which does more stuff (quoting
 216	 * from UM11040):
 217	 *
 218	 *   A write request is accepted only when HOSTCMD is set to write host
 219	 *   or invalid. A read request is accepted only when HOSTCMD is set to
 220	 *   search host or read host.
 221	 *
 222	 * So it is possible to translate a RDWRSET/VALIDENT combination into
 223	 * HOSTCMD so that we keep the dynamic command API in place, and
 224	 * at the same time achieve compatibility with the management route
 225	 * command structure.
 226	 */
 227	if (cmd->rdwrset == SPI_READ) {
 228		if (cmd->search)
 229			hostcmd = SJA1105_HOSTCMD_SEARCH;
 230		else
 231			hostcmd = SJA1105_HOSTCMD_READ;
 232	} else {
 233		/* SPI_WRITE */
 234		if (cmd->valident)
 235			hostcmd = SJA1105_HOSTCMD_WRITE;
 236		else
 237			hostcmd = SJA1105_HOSTCMD_INVALIDATE;
 238	}
 239	sja1105_packing(p, &hostcmd, 25, 23, size, op);
 240
 241	/* Hack - The hardware takes the 'index' field within
 242	 * struct sja1105_l2_lookup_entry as the index on which this command
 243	 * will operate. However it will ignore everything else, so 'index'
 244	 * is logically part of command but physically part of entry.
 245	 * Populate the 'index' entry field from within the command callback,
 246	 * such that our API doesn't need to ask for a full-blown entry
 247	 * structure when e.g. a delete is requested.
 248	 */
 249	sja1105_packing(buf, &cmd->index, 15, 6,
 250			SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY, op);
 251}
 252
 253/* The switch is so retarded that it makes our command/entry abstraction
 254 * crumble apart.
 255 *
 256 * On P/Q/R/S, the switch tries to say whether a FDB entry
 257 * is statically programmed or dynamically learned via a flag called LOCKEDS.
 258 * The hardware manual says about this fiels:
 259 *
 260 *   On write will specify the format of ENTRY.
 261 *   On read the flag will be found cleared at times the VALID flag is found
 262 *   set.  The flag will also be found cleared in response to a read having the
 263 *   MGMTROUTE flag set.  In response to a read with the MGMTROUTE flag
 264 *   cleared, the flag be set if the most recent access operated on an entry
 265 *   that was either loaded by configuration or through dynamic reconfiguration
 266 *   (as opposed to automatically learned entries).
 267 *
 268 * The trouble with this flag is that it's part of the *command* to access the
 269 * dynamic interface, and not part of the *entry* retrieved from it.
 270 * Otherwise said, for a sja1105_dynamic_config_read, LOCKEDS is supposed to be
 271 * an output from the switch into the command buffer, and for a
 272 * sja1105_dynamic_config_write, the switch treats LOCKEDS as an input
 273 * (hence we can write either static, or automatically learned entries, from
 274 * the core).
 275 * But the manual contradicts itself in the last phrase where it says that on
 276 * read, LOCKEDS will be set to 1 for all FDB entries written through the
 277 * dynamic interface (therefore, the value of LOCKEDS from the
 278 * sja1105_dynamic_config_write is not really used for anything, it'll store a
 279 * 1 anyway).
 280 * This means you can't really write a FDB entry with LOCKEDS=0 (automatically
 281 * learned) into the switch, which kind of makes sense.
 282 * As for reading through the dynamic interface, it doesn't make too much sense
 283 * to put LOCKEDS into the command, since the switch will inevitably have to
 284 * ignore it (otherwise a command would be like "read the FDB entry 123, but
 285 * only if it's dynamically learned" <- well how am I supposed to know?) and
 286 * just use it as an output buffer for its findings. But guess what... that's
 287 * what the entry buffer is for!
 288 * Unfortunately, what really breaks this abstraction is the fact that it
 289 * wasn't designed having the fact in mind that the switch can output
 290 * entry-related data as writeback through the command buffer.
 291 * However, whether a FDB entry is statically or dynamically learned *is* part
 292 * of the entry and not the command data, no matter what the switch thinks.
 293 * In order to do that, we'll need to wrap around the
 294 * sja1105pqrs_l2_lookup_entry_packing from sja1105_static_config.c, and take
 295 * a peek outside of the caller-supplied @buf (the entry buffer), to reach the
 296 * command buffer.
 297 */
 298static size_t
 299sja1105pqrs_dyn_l2_lookup_entry_packing(void *buf, void *entry_ptr,
 300					enum packing_op op)
 301{
 302	struct sja1105_l2_lookup_entry *entry = entry_ptr;
 303	u8 *cmd = buf + SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY;
 304	const int size = SJA1105_SIZE_DYN_CMD;
 305
 306	sja1105_packing(cmd, &entry->lockeds, 28, 28, size, op);
 307
 308	return sja1105pqrs_l2_lookup_entry_packing(buf, entry_ptr, op);
 309}
 310
 311static void
 312sja1105et_l2_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
 313				enum packing_op op)
 314{
 315	u8 *p = buf + SJA1105ET_SIZE_L2_LOOKUP_ENTRY;
 316	const int size = SJA1105_SIZE_DYN_CMD;
 317
 318	sja1105_packing(p, &cmd->valid,    31, 31, size, op);
 319	sja1105_packing(p, &cmd->rdwrset,  30, 30, size, op);
 320	sja1105_packing(p, &cmd->errors,   29, 29, size, op);
 321	sja1105_packing(p, &cmd->valident, 27, 27, size, op);
 322	/* Hack - see comments above. */
 323	sja1105_packing(buf, &cmd->index, 29, 20,
 324			SJA1105ET_SIZE_L2_LOOKUP_ENTRY, op);
 325}
 326
 327static size_t sja1105et_dyn_l2_lookup_entry_packing(void *buf, void *entry_ptr,
 328						    enum packing_op op)
 329{
 330	struct sja1105_l2_lookup_entry *entry = entry_ptr;
 331	u8 *cmd = buf + SJA1105ET_SIZE_L2_LOOKUP_ENTRY;
 332	const int size = SJA1105_SIZE_DYN_CMD;
 333
 334	sja1105_packing(cmd, &entry->lockeds, 28, 28, size, op);
 335
 336	return sja1105et_l2_lookup_entry_packing(buf, entry_ptr, op);
 337}
 338
 339static void
 340sja1105et_mgmt_route_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
 341				 enum packing_op op)
 342{
 343	u8 *p = buf + SJA1105ET_SIZE_L2_LOOKUP_ENTRY;
 344	u64 mgmtroute = 1;
 345
 346	sja1105et_l2_lookup_cmd_packing(buf, cmd, op);
 347	if (op == PACK)
 348		sja1105_pack(p, &mgmtroute, 26, 26, SJA1105_SIZE_DYN_CMD);
 349}
 350
 351static size_t sja1105et_mgmt_route_entry_packing(void *buf, void *entry_ptr,
 352						 enum packing_op op)
 353{
 354	struct sja1105_mgmt_entry *entry = entry_ptr;
 355	const size_t size = SJA1105ET_SIZE_L2_LOOKUP_ENTRY;
 356
 357	/* UM10944: To specify if a PTP egress timestamp shall be captured on
 358	 * each port upon transmission of the frame, the LSB of VLANID in the
 359	 * ENTRY field provided by the host must be set.
 360	 * Bit 1 of VLANID then specifies the register where the timestamp for
 361	 * this port is stored in.
 362	 */
 363	sja1105_packing(buf, &entry->tsreg,     85, 85, size, op);
 364	sja1105_packing(buf, &entry->takets,    84, 84, size, op);
 365	sja1105_packing(buf, &entry->macaddr,   83, 36, size, op);
 366	sja1105_packing(buf, &entry->destports, 35, 31, size, op);
 367	sja1105_packing(buf, &entry->enfport,   30, 30, size, op);
 368	return size;
 369}
 370
 371static void
 372sja1105pqrs_mgmt_route_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
 373				   enum packing_op op)
 374{
 375	u8 *p = buf + SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY;
 376	u64 mgmtroute = 1;
 377
 378	sja1105pqrs_l2_lookup_cmd_packing(buf, cmd, op);
 379	if (op == PACK)
 380		sja1105_pack(p, &mgmtroute, 26, 26, SJA1105_SIZE_DYN_CMD);
 381}
 382
 383static size_t sja1105pqrs_mgmt_route_entry_packing(void *buf, void *entry_ptr,
 384						   enum packing_op op)
 385{
 386	const size_t size = SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY;
 387	struct sja1105_mgmt_entry *entry = entry_ptr;
 388
 389	/* In P/Q/R/S, enfport got renamed to mgmtvalid, but its purpose
 390	 * is the same (driver uses it to confirm that frame was sent).
 391	 * So just keep the name from E/T.
 392	 */
 393	sja1105_packing(buf, &entry->tsreg,     71, 71, size, op);
 394	sja1105_packing(buf, &entry->takets,    70, 70, size, op);
 395	sja1105_packing(buf, &entry->macaddr,   69, 22, size, op);
 396	sja1105_packing(buf, &entry->destports, 21, 17, size, op);
 397	sja1105_packing(buf, &entry->enfport,   16, 16, size, op);
 398	return size;
 399}
 400
 401/* In E/T, entry is at addresses 0x27-0x28. There is a 4 byte gap at 0x29,
 402 * and command is at 0x2a. Similarly in P/Q/R/S there is a 1 register gap
 403 * between entry (0x2d, 0x2e) and command (0x30).
 404 */
 405static void
 406sja1105_vlan_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
 407				enum packing_op op)
 408{
 409	u8 *p = buf + SJA1105_SIZE_VLAN_LOOKUP_ENTRY + 4;
 410	const int size = SJA1105_SIZE_DYN_CMD;
 411
 412	sja1105_packing(p, &cmd->valid,    31, 31, size, op);
 413	sja1105_packing(p, &cmd->rdwrset,  30, 30, size, op);
 414	sja1105_packing(p, &cmd->valident, 27, 27, size, op);
 415	/* Hack - see comments above, applied for 'vlanid' field of
 416	 * struct sja1105_vlan_lookup_entry.
 417	 */
 418	sja1105_packing(buf, &cmd->index, 38, 27,
 419			SJA1105_SIZE_VLAN_LOOKUP_ENTRY, op);
 420}
 421
 422static void
 423sja1105_l2_forwarding_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
 424				  enum packing_op op)
 425{
 426	u8 *p = buf + SJA1105_SIZE_L2_FORWARDING_ENTRY;
 427	const int size = SJA1105_SIZE_DYN_CMD;
 428
 429	sja1105_packing(p, &cmd->valid,   31, 31, size, op);
 430	sja1105_packing(p, &cmd->errors,  30, 30, size, op);
 431	sja1105_packing(p, &cmd->rdwrset, 29, 29, size, op);
 432	sja1105_packing(p, &cmd->index,    4,  0, size, op);
 433}
 434
 435static void
 436sja1105et_mac_config_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
 437				 enum packing_op op)
 438{
 439	const int size = SJA1105_SIZE_DYN_CMD;
 440	/* Yup, user manual definitions are reversed */
 441	u8 *reg1 = buf + 4;
 442
 443	sja1105_packing(reg1, &cmd->valid, 31, 31, size, op);
 444	sja1105_packing(reg1, &cmd->index, 26, 24, size, op);
 445}
 446
 447static size_t sja1105et_mac_config_entry_packing(void *buf, void *entry_ptr,
 448						 enum packing_op op)
 449{
 450	const int size = SJA1105ET_SIZE_MAC_CONFIG_DYN_ENTRY;
 451	struct sja1105_mac_config_entry *entry = entry_ptr;
 452	/* Yup, user manual definitions are reversed */
 453	u8 *reg1 = buf + 4;
 454	u8 *reg2 = buf;
 455
 456	sja1105_packing(reg1, &entry->speed,     30, 29, size, op);
 457	sja1105_packing(reg1, &entry->drpdtag,   23, 23, size, op);
 458	sja1105_packing(reg1, &entry->drpuntag,  22, 22, size, op);
 459	sja1105_packing(reg1, &entry->retag,     21, 21, size, op);
 460	sja1105_packing(reg1, &entry->dyn_learn, 20, 20, size, op);
 461	sja1105_packing(reg1, &entry->egress,    19, 19, size, op);
 462	sja1105_packing(reg1, &entry->ingress,   18, 18, size, op);
 463	sja1105_packing(reg1, &entry->ing_mirr,  17, 17, size, op);
 464	sja1105_packing(reg1, &entry->egr_mirr,  16, 16, size, op);
 465	sja1105_packing(reg1, &entry->vlanprio,  14, 12, size, op);
 466	sja1105_packing(reg1, &entry->vlanid,    11,  0, size, op);
 467	sja1105_packing(reg2, &entry->tp_delin,  31, 16, size, op);
 468	sja1105_packing(reg2, &entry->tp_delout, 15,  0, size, op);
 469	/* MAC configuration table entries which can't be reconfigured:
 470	 * top, base, enabled, ifg, maxage, drpnona664
 471	 */
 472	/* Bogus return value, not used anywhere */
 473	return 0;
 474}
 475
 476static void
 477sja1105pqrs_mac_config_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
 478				   enum packing_op op)
 479{
 480	const int size = SJA1105ET_SIZE_MAC_CONFIG_DYN_ENTRY;
 481	u8 *p = buf + SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY;
 482
 483	sja1105_packing(p, &cmd->valid,   31, 31, size, op);
 484	sja1105_packing(p, &cmd->errors,  30, 30, size, op);
 485	sja1105_packing(p, &cmd->rdwrset, 29, 29, size, op);
 486	sja1105_packing(p, &cmd->index,    2,  0, size, op);
 487}
 488
 489static void
 490sja1105et_l2_lookup_params_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
 491				       enum packing_op op)
 492{
 493	sja1105_packing(buf, &cmd->valid, 31, 31,
 494			SJA1105ET_SIZE_L2_LOOKUP_PARAMS_DYN_CMD, op);
 495}
 496
 497static size_t
 498sja1105et_l2_lookup_params_entry_packing(void *buf, void *entry_ptr,
 499					 enum packing_op op)
 500{
 501	struct sja1105_l2_lookup_params_entry *entry = entry_ptr;
 502
 503	sja1105_packing(buf, &entry->poly, 7, 0,
 504			SJA1105ET_SIZE_L2_LOOKUP_PARAMS_DYN_CMD, op);
 505	/* Bogus return value, not used anywhere */
 506	return 0;
 507}
 508
 509static void
 510sja1105pqrs_l2_lookup_params_cmd_packing(void *buf,
 511					 struct sja1105_dyn_cmd *cmd,
 512					 enum packing_op op)
 513{
 514	u8 *p = buf + SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_ENTRY;
 515	const int size = SJA1105_SIZE_DYN_CMD;
 516
 517	sja1105_packing(p, &cmd->valid,   31, 31, size, op);
 518	sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op);
 519}
 520
 521static void
 522sja1105et_general_params_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
 523				     enum packing_op op)
 524{
 525	const int size = SJA1105ET_SIZE_GENERAL_PARAMS_DYN_CMD;
 526
 527	sja1105_packing(buf, &cmd->valid,  31, 31, size, op);
 528	sja1105_packing(buf, &cmd->errors, 30, 30, size, op);
 529}
 530
 531static size_t
 532sja1105et_general_params_entry_packing(void *buf, void *entry_ptr,
 533				       enum packing_op op)
 534{
 535	struct sja1105_general_params_entry *entry = entry_ptr;
 536	const int size = SJA1105ET_SIZE_GENERAL_PARAMS_DYN_CMD;
 537
 538	sja1105_packing(buf, &entry->mirr_port, 2, 0, size, op);
 539	/* Bogus return value, not used anywhere */
 540	return 0;
 541}
 542
 543static void
 544sja1105pqrs_general_params_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
 545				       enum packing_op op)
 546{
 547	u8 *p = buf + SJA1105PQRS_SIZE_GENERAL_PARAMS_ENTRY;
 548	const int size = SJA1105_SIZE_DYN_CMD;
 549
 550	sja1105_packing(p, &cmd->valid,   31, 31, size, op);
 551	sja1105_packing(p, &cmd->errors,  30, 30, size, op);
 552	sja1105_packing(p, &cmd->rdwrset, 28, 28, size, op);
 553}
 554
 555static void
 556sja1105pqrs_avb_params_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
 557				   enum packing_op op)
 558{
 559	u8 *p = buf + SJA1105PQRS_SIZE_AVB_PARAMS_ENTRY;
 560	const int size = SJA1105_SIZE_DYN_CMD;
 561
 562	sja1105_packing(p, &cmd->valid,   31, 31, size, op);
 563	sja1105_packing(p, &cmd->errors,  30, 30, size, op);
 564	sja1105_packing(p, &cmd->rdwrset, 29, 29, size, op);
 565}
 566
 567static void
 568sja1105_retagging_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
 569			      enum packing_op op)
 570{
 571	u8 *p = buf + SJA1105_SIZE_RETAGGING_ENTRY;
 572	const int size = SJA1105_SIZE_DYN_CMD;
 573
 574	sja1105_packing(p, &cmd->valid,    31, 31, size, op);
 575	sja1105_packing(p, &cmd->errors,   30, 30, size, op);
 576	sja1105_packing(p, &cmd->valident, 29, 29, size, op);
 577	sja1105_packing(p, &cmd->rdwrset,  28, 28, size, op);
 578	sja1105_packing(p, &cmd->index,     5,  0, size, op);
 579}
 580
 581static void sja1105et_cbs_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
 582				      enum packing_op op)
 583{
 584	u8 *p = buf + SJA1105ET_SIZE_CBS_ENTRY;
 585	const int size = SJA1105_SIZE_DYN_CMD;
 586
 587	sja1105_packing(p, &cmd->valid, 31, 31, size, op);
 588	sja1105_packing(p, &cmd->index, 19, 16, size, op);
 589}
 590
 591static size_t sja1105et_cbs_entry_packing(void *buf, void *entry_ptr,
 592					  enum packing_op op)
 593{
 594	const size_t size = SJA1105ET_SIZE_CBS_ENTRY;
 595	struct sja1105_cbs_entry *entry = entry_ptr;
 596	u8 *cmd = buf + size;
 597	u32 *p = buf;
 598
 599	sja1105_packing(cmd, &entry->port, 5, 3, SJA1105_SIZE_DYN_CMD, op);
 600	sja1105_packing(cmd, &entry->prio, 2, 0, SJA1105_SIZE_DYN_CMD, op);
 601	sja1105_packing(p + 3, &entry->credit_lo,  31, 0, size, op);
 602	sja1105_packing(p + 2, &entry->credit_hi,  31, 0, size, op);
 603	sja1105_packing(p + 1, &entry->send_slope, 31, 0, size, op);
 604	sja1105_packing(p + 0, &entry->idle_slope, 31, 0, size, op);
 605	return size;
 606}
 607
 608static void sja1105pqrs_cbs_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
 609					enum packing_op op)
 610{
 611	u8 *p = buf + SJA1105PQRS_SIZE_CBS_ENTRY;
 612	const int size = SJA1105_SIZE_DYN_CMD;
 613
 614	sja1105_packing(p, &cmd->valid,   31, 31, size, op);
 615	sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op);
 616	sja1105_packing(p, &cmd->errors,  29, 29, size, op);
 617	sja1105_packing(p, &cmd->index,    3,  0, size, op);
 618}
 619
 620static size_t sja1105pqrs_cbs_entry_packing(void *buf, void *entry_ptr,
 621					    enum packing_op op)
 622{
 623	const size_t size = SJA1105PQRS_SIZE_CBS_ENTRY;
 624	struct sja1105_cbs_entry *entry = entry_ptr;
 625
 626	sja1105_packing(buf, &entry->port,      159, 157, size, op);
 627	sja1105_packing(buf, &entry->prio,      156, 154, size, op);
 628	sja1105_packing(buf, &entry->credit_lo, 153, 122, size, op);
 629	sja1105_packing(buf, &entry->credit_hi, 121,  90, size, op);
 630	sja1105_packing(buf, &entry->send_slope, 89,  58, size, op);
 631	sja1105_packing(buf, &entry->idle_slope, 57,  26, size, op);
 632	return size;
 633}
 634
 635#define OP_READ		BIT(0)
 636#define OP_WRITE	BIT(1)
 637#define OP_DEL		BIT(2)
 638#define OP_SEARCH	BIT(3)
 639
 640/* SJA1105E/T: First generation */
 641const struct sja1105_dynamic_table_ops sja1105et_dyn_ops[BLK_IDX_MAX_DYN] = {
 642	[BLK_IDX_VL_LOOKUP] = {
 643		.entry_packing = sja1105et_vl_lookup_entry_packing,
 644		.cmd_packing = sja1105_vl_lookup_cmd_packing,
 645		.access = OP_WRITE,
 646		.max_entry_count = SJA1105_MAX_VL_LOOKUP_COUNT,
 647		.packed_size = SJA1105ET_SJA1105_SIZE_VL_LOOKUP_DYN_CMD,
 648		.addr = 0x35,
 649	},
 650	[BLK_IDX_L2_LOOKUP] = {
 651		.entry_packing = sja1105et_dyn_l2_lookup_entry_packing,
 652		.cmd_packing = sja1105et_l2_lookup_cmd_packing,
 653		.access = (OP_READ | OP_WRITE | OP_DEL),
 654		.max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT,
 655		.packed_size = SJA1105ET_SIZE_L2_LOOKUP_DYN_CMD,
 656		.addr = 0x20,
 657	},
 658	[BLK_IDX_MGMT_ROUTE] = {
 659		.entry_packing = sja1105et_mgmt_route_entry_packing,
 660		.cmd_packing = sja1105et_mgmt_route_cmd_packing,
 661		.access = (OP_READ | OP_WRITE),
 662		.max_entry_count = SJA1105_NUM_PORTS,
 663		.packed_size = SJA1105ET_SIZE_L2_LOOKUP_DYN_CMD,
 664		.addr = 0x20,
 665	},
 666	[BLK_IDX_VLAN_LOOKUP] = {
 667		.entry_packing = sja1105_vlan_lookup_entry_packing,
 668		.cmd_packing = sja1105_vlan_lookup_cmd_packing,
 669		.access = (OP_WRITE | OP_DEL),
 670		.max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT,
 671		.packed_size = SJA1105_SIZE_VLAN_LOOKUP_DYN_CMD,
 672		.addr = 0x27,
 673	},
 674	[BLK_IDX_L2_FORWARDING] = {
 675		.entry_packing = sja1105_l2_forwarding_entry_packing,
 676		.cmd_packing = sja1105_l2_forwarding_cmd_packing,
 677		.max_entry_count = SJA1105_MAX_L2_FORWARDING_COUNT,
 678		.access = OP_WRITE,
 679		.packed_size = SJA1105_SIZE_L2_FORWARDING_DYN_CMD,
 680		.addr = 0x24,
 681	},
 682	[BLK_IDX_MAC_CONFIG] = {
 683		.entry_packing = sja1105et_mac_config_entry_packing,
 684		.cmd_packing = sja1105et_mac_config_cmd_packing,
 685		.max_entry_count = SJA1105_MAX_MAC_CONFIG_COUNT,
 686		.access = OP_WRITE,
 687		.packed_size = SJA1105ET_SIZE_MAC_CONFIG_DYN_CMD,
 688		.addr = 0x36,
 689	},
 690	[BLK_IDX_L2_LOOKUP_PARAMS] = {
 691		.entry_packing = sja1105et_l2_lookup_params_entry_packing,
 692		.cmd_packing = sja1105et_l2_lookup_params_cmd_packing,
 693		.max_entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT,
 694		.access = OP_WRITE,
 695		.packed_size = SJA1105ET_SIZE_L2_LOOKUP_PARAMS_DYN_CMD,
 696		.addr = 0x38,
 697	},
 698	[BLK_IDX_GENERAL_PARAMS] = {
 699		.entry_packing = sja1105et_general_params_entry_packing,
 700		.cmd_packing = sja1105et_general_params_cmd_packing,
 701		.max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT,
 702		.access = OP_WRITE,
 703		.packed_size = SJA1105ET_SIZE_GENERAL_PARAMS_DYN_CMD,
 704		.addr = 0x34,
 705	},
 706	[BLK_IDX_RETAGGING] = {
 707		.entry_packing = sja1105_retagging_entry_packing,
 708		.cmd_packing = sja1105_retagging_cmd_packing,
 709		.max_entry_count = SJA1105_MAX_RETAGGING_COUNT,
 710		.access = (OP_WRITE | OP_DEL),
 711		.packed_size = SJA1105_SIZE_RETAGGING_DYN_CMD,
 712		.addr = 0x31,
 713	},
 714	[BLK_IDX_CBS] = {
 715		.entry_packing = sja1105et_cbs_entry_packing,
 716		.cmd_packing = sja1105et_cbs_cmd_packing,
 717		.max_entry_count = SJA1105ET_MAX_CBS_COUNT,
 718		.access = OP_WRITE,
 719		.packed_size = SJA1105ET_SIZE_CBS_DYN_CMD,
 720		.addr = 0x2c,
 721	},
 722};
 723
 724/* SJA1105P/Q/R/S: Second generation */
 725const struct sja1105_dynamic_table_ops sja1105pqrs_dyn_ops[BLK_IDX_MAX_DYN] = {
 726	[BLK_IDX_VL_LOOKUP] = {
 727		.entry_packing = sja1105_vl_lookup_entry_packing,
 728		.cmd_packing = sja1105_vl_lookup_cmd_packing,
 729		.access = (OP_READ | OP_WRITE),
 730		.max_entry_count = SJA1105_MAX_VL_LOOKUP_COUNT,
 731		.packed_size = SJA1105PQRS_SJA1105_SIZE_VL_LOOKUP_DYN_CMD,
 732		.addr = 0x47,
 733	},
 734	[BLK_IDX_L2_LOOKUP] = {
 735		.entry_packing = sja1105pqrs_dyn_l2_lookup_entry_packing,
 736		.cmd_packing = sja1105pqrs_l2_lookup_cmd_packing,
 737		.access = (OP_READ | OP_WRITE | OP_DEL | OP_SEARCH),
 738		.max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT,
 739		.packed_size = SJA1105PQRS_SIZE_L2_LOOKUP_DYN_CMD,
 740		.addr = 0x24,
 741	},
 742	[BLK_IDX_MGMT_ROUTE] = {
 743		.entry_packing = sja1105pqrs_mgmt_route_entry_packing,
 744		.cmd_packing = sja1105pqrs_mgmt_route_cmd_packing,
 745		.access = (OP_READ | OP_WRITE | OP_DEL | OP_SEARCH),
 746		.max_entry_count = SJA1105_NUM_PORTS,
 747		.packed_size = SJA1105PQRS_SIZE_L2_LOOKUP_DYN_CMD,
 748		.addr = 0x24,
 749	},
 750	[BLK_IDX_VLAN_LOOKUP] = {
 751		.entry_packing = sja1105_vlan_lookup_entry_packing,
 752		.cmd_packing = sja1105_vlan_lookup_cmd_packing,
 753		.access = (OP_READ | OP_WRITE | OP_DEL),
 754		.max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT,
 755		.packed_size = SJA1105_SIZE_VLAN_LOOKUP_DYN_CMD,
 756		.addr = 0x2D,
 757	},
 758	[BLK_IDX_L2_FORWARDING] = {
 759		.entry_packing = sja1105_l2_forwarding_entry_packing,
 760		.cmd_packing = sja1105_l2_forwarding_cmd_packing,
 761		.max_entry_count = SJA1105_MAX_L2_FORWARDING_COUNT,
 762		.access = OP_WRITE,
 763		.packed_size = SJA1105_SIZE_L2_FORWARDING_DYN_CMD,
 764		.addr = 0x2A,
 765	},
 766	[BLK_IDX_MAC_CONFIG] = {
 767		.entry_packing = sja1105pqrs_mac_config_entry_packing,
 768		.cmd_packing = sja1105pqrs_mac_config_cmd_packing,
 769		.max_entry_count = SJA1105_MAX_MAC_CONFIG_COUNT,
 770		.access = (OP_READ | OP_WRITE),
 771		.packed_size = SJA1105PQRS_SIZE_MAC_CONFIG_DYN_CMD,
 772		.addr = 0x4B,
 773	},
 774	[BLK_IDX_L2_LOOKUP_PARAMS] = {
 775		.entry_packing = sja1105pqrs_l2_lookup_params_entry_packing,
 776		.cmd_packing = sja1105pqrs_l2_lookup_params_cmd_packing,
 777		.max_entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT,
 778		.access = (OP_READ | OP_WRITE),
 779		.packed_size = SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_DYN_CMD,
 780		.addr = 0x54,
 781	},
 782	[BLK_IDX_AVB_PARAMS] = {
 783		.entry_packing = sja1105pqrs_avb_params_entry_packing,
 784		.cmd_packing = sja1105pqrs_avb_params_cmd_packing,
 785		.max_entry_count = SJA1105_MAX_AVB_PARAMS_COUNT,
 786		.access = (OP_READ | OP_WRITE),
 787		.packed_size = SJA1105PQRS_SIZE_AVB_PARAMS_DYN_CMD,
 788		.addr = 0x8003,
 789	},
 790	[BLK_IDX_GENERAL_PARAMS] = {
 791		.entry_packing = sja1105pqrs_general_params_entry_packing,
 792		.cmd_packing = sja1105pqrs_general_params_cmd_packing,
 793		.max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT,
 794		.access = (OP_READ | OP_WRITE),
 795		.packed_size = SJA1105PQRS_SIZE_GENERAL_PARAMS_DYN_CMD,
 796		.addr = 0x3B,
 797	},
 798	[BLK_IDX_RETAGGING] = {
 799		.entry_packing = sja1105_retagging_entry_packing,
 800		.cmd_packing = sja1105_retagging_cmd_packing,
 801		.max_entry_count = SJA1105_MAX_RETAGGING_COUNT,
 802		.access = (OP_READ | OP_WRITE | OP_DEL),
 803		.packed_size = SJA1105_SIZE_RETAGGING_DYN_CMD,
 804		.addr = 0x38,
 805	},
 806	[BLK_IDX_CBS] = {
 807		.entry_packing = sja1105pqrs_cbs_entry_packing,
 808		.cmd_packing = sja1105pqrs_cbs_cmd_packing,
 809		.max_entry_count = SJA1105PQRS_MAX_CBS_COUNT,
 810		.access = OP_WRITE,
 811		.packed_size = SJA1105PQRS_SIZE_CBS_DYN_CMD,
 812		.addr = 0x32,
 813	},
 814};
 815
 816/* Provides read access to the settings through the dynamic interface
 817 * of the switch.
 818 * @blk_idx	is used as key to select from the sja1105_dynamic_table_ops.
 819 *		The selection is limited by the hardware in respect to which
 820 *		configuration blocks can be read through the dynamic interface.
 821 * @index	is used to retrieve a particular table entry. If negative,
 822 *		(and if the @blk_idx supports the searching operation) a search
 823 *		is performed by the @entry parameter.
 824 * @entry	Type-casted to an unpacked structure that holds a table entry
 825 *		of the type specified in @blk_idx.
 826 *		Usually an output argument. If @index is negative, then this
 827 *		argument is used as input/output: it should be pre-populated
 828 *		with the element to search for. Entries which support the
 829 *		search operation will have an "index" field (not the @index
 830 *		argument to this function) and that is where the found index
 831 *		will be returned (or left unmodified - thus negative - if not
 832 *		found).
 833 */
 834int sja1105_dynamic_config_read(struct sja1105_private *priv,
 835				enum sja1105_blk_idx blk_idx,
 836				int index, void *entry)
 837{
 838	const struct sja1105_dynamic_table_ops *ops;
 839	struct sja1105_dyn_cmd cmd = {0};
 840	/* SPI payload buffer */
 841	u8 packed_buf[SJA1105_MAX_DYN_CMD_SIZE] = {0};
 842	int retries = 3;
 843	int rc;
 844
 845	if (blk_idx >= BLK_IDX_MAX_DYN)
 846		return -ERANGE;
 847
 848	ops = &priv->info->dyn_ops[blk_idx];
 849
 850	if (index >= 0 && index >= ops->max_entry_count)
 851		return -ERANGE;
 852	if (index < 0 && !(ops->access & OP_SEARCH))
 853		return -EOPNOTSUPP;
 854	if (!(ops->access & OP_READ))
 855		return -EOPNOTSUPP;
 856	if (ops->packed_size > SJA1105_MAX_DYN_CMD_SIZE)
 857		return -ERANGE;
 858	if (!ops->cmd_packing)
 859		return -EOPNOTSUPP;
 860	if (!ops->entry_packing)
 861		return -EOPNOTSUPP;
 862
 863	cmd.valid = true; /* Trigger action on table entry */
 864	cmd.rdwrset = SPI_READ; /* Action is read */
 865	if (index < 0) {
 866		/* Avoid copying a signed negative number to an u64 */
 867		cmd.index = 0;
 868		cmd.search = true;
 869	} else {
 870		cmd.index = index;
 871		cmd.search = false;
 872	}
 873	cmd.valident = true;
 874	ops->cmd_packing(packed_buf, &cmd, PACK);
 875
 876	if (cmd.search)
 877		ops->entry_packing(packed_buf, entry, PACK);
 878
 879	/* Send SPI write operation: read config table entry */
 880	rc = sja1105_xfer_buf(priv, SPI_WRITE, ops->addr, packed_buf,
 881			      ops->packed_size);
 882	if (rc < 0)
 883		return rc;
 884
 885	/* Loop until we have confirmation that hardware has finished
 886	 * processing the command and has cleared the VALID field
 887	 */
 888	do {
 889		memset(packed_buf, 0, ops->packed_size);
 890
 891		/* Retrieve the read operation's result */
 892		rc = sja1105_xfer_buf(priv, SPI_READ, ops->addr, packed_buf,
 893				      ops->packed_size);
 894		if (rc < 0)
 895			return rc;
 896
 897		cmd = (struct sja1105_dyn_cmd) {0};
 898		ops->cmd_packing(packed_buf, &cmd, UNPACK);
 899		/* UM10944: [valident] will always be found cleared
 900		 * during a read access with MGMTROUTE set.
 901		 * So don't error out in that case.
 902		 */
 903		if (!cmd.valident && blk_idx != BLK_IDX_MGMT_ROUTE)
 904			return -ENOENT;
 905		cpu_relax();
 906	} while (cmd.valid && --retries);
 907
 908	if (cmd.valid)
 909		return -ETIMEDOUT;
 910
 911	/* Don't dereference possibly NULL pointer - maybe caller
 912	 * only wanted to see whether the entry existed or not.
 913	 */
 914	if (entry)
 915		ops->entry_packing(packed_buf, entry, UNPACK);
 916	return 0;
 917}
 918
 919int sja1105_dynamic_config_write(struct sja1105_private *priv,
 920				 enum sja1105_blk_idx blk_idx,
 921				 int index, void *entry, bool keep)
 922{
 923	const struct sja1105_dynamic_table_ops *ops;
 924	struct sja1105_dyn_cmd cmd = {0};
 925	/* SPI payload buffer */
 926	u8 packed_buf[SJA1105_MAX_DYN_CMD_SIZE] = {0};
 927	int rc;
 928
 929	if (blk_idx >= BLK_IDX_MAX_DYN)
 930		return -ERANGE;
 931
 932	ops = &priv->info->dyn_ops[blk_idx];
 933
 934	if (index >= ops->max_entry_count)
 935		return -ERANGE;
 936	if (index < 0)
 937		return -ERANGE;
 938	if (!(ops->access & OP_WRITE))
 939		return -EOPNOTSUPP;
 940	if (!keep && !(ops->access & OP_DEL))
 941		return -EOPNOTSUPP;
 942	if (ops->packed_size > SJA1105_MAX_DYN_CMD_SIZE)
 943		return -ERANGE;
 944
 945	cmd.valident = keep; /* If false, deletes entry */
 946	cmd.valid = true; /* Trigger action on table entry */
 947	cmd.rdwrset = SPI_WRITE; /* Action is write */
 948	cmd.index = index;
 949
 950	if (!ops->cmd_packing)
 951		return -EOPNOTSUPP;
 952	ops->cmd_packing(packed_buf, &cmd, PACK);
 953
 954	if (!ops->entry_packing)
 955		return -EOPNOTSUPP;
 956	/* Don't dereference potentially NULL pointer if just
 957	 * deleting a table entry is what was requested. For cases
 958	 * where 'index' field is physically part of entry structure,
 959	 * and needed here, we deal with that in the cmd_packing callback.
 960	 */
 961	if (keep)
 962		ops->entry_packing(packed_buf, entry, PACK);
 963
 964	/* Send SPI write operation: read config table entry */
 965	rc = sja1105_xfer_buf(priv, SPI_WRITE, ops->addr, packed_buf,
 966			      ops->packed_size);
 967	if (rc < 0)
 968		return rc;
 969
 970	cmd = (struct sja1105_dyn_cmd) {0};
 971	ops->cmd_packing(packed_buf, &cmd, UNPACK);
 972	if (cmd.errors)
 973		return -EINVAL;
 974
 975	return 0;
 976}
 977
 978static u8 sja1105_crc8_add(u8 crc, u8 byte, u8 poly)
 979{
 980	int i;
 981
 982	for (i = 0; i < 8; i++) {
 983		if ((crc ^ byte) & (1 << 7)) {
 984			crc <<= 1;
 985			crc ^= poly;
 986		} else {
 987			crc <<= 1;
 988		}
 989		byte <<= 1;
 990	}
 991	return crc;
 992}
 993
 994/* CRC8 algorithm with non-reversed input, non-reversed output,
 995 * no input xor and no output xor. Code customized for receiving
 996 * the SJA1105 E/T FDB keys (vlanid, macaddr) as input. CRC polynomial
 997 * is also received as argument in the Koopman notation that the switch
 998 * hardware stores it in.
 999 */
1000u8 sja1105et_fdb_hash(struct sja1105_private *priv, const u8 *addr, u16 vid)
1001{
1002	struct sja1105_l2_lookup_params_entry *l2_lookup_params =
1003		priv->static_config.tables[BLK_IDX_L2_LOOKUP_PARAMS].entries;
1004	u64 poly_koopman = l2_lookup_params->poly;
1005	/* Convert polynomial from Koopman to 'normal' notation */
1006	u8 poly = (u8)(1 + (poly_koopman << 1));
1007	u64 vlanid = l2_lookup_params->shared_learn ? 0 : vid;
1008	u64 input = (vlanid << 48) | ether_addr_to_u64(addr);
1009	u8 crc = 0; /* seed */
1010	int i;
1011
1012	/* Mask the eight bytes starting from MSB one at a time */
1013	for (i = 56; i >= 0; i -= 8) {
1014		u8 byte = (input & (0xffull << i)) >> i;
1015
1016		crc = sja1105_crc8_add(crc, byte, poly);
1017	}
1018	return crc;
1019}