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  *	OP_VALID_ANYWAY: Reading some tables through the dynamic config
82  *			 interface is possible even if the VALIDENT bit is not
83  *			 set in the writeback. So don't error out in that case.
84  * - .max_entry_count: The number of entries, counting from zero, that can be
85  *		       reconfigured through the dynamic interface. If a static
86  *		       table can be reconfigured at all dynamically, this
87  *		       number always matches the maximum number of supported
88  *		       static entries.
89  * - .packed_size: The length in bytes of the compound ENTRY + COMMAND BUFFER.
90  *		   Note that sometimes the compound buffer may contain holes in
91  *		   it (see sja1105_vlan_lookup_cmd_packing). The @packed_buf is
92  *		   contiguous however, so @packed_size includes any unused
93  *		   bytes.
94  * - .addr: The base SPI address at which the buffer must be written to the
95  *	    switch's memory. When looking at the hardware manual, this must
96  *	    always match the lowest documented address for the ENTRY, and not
97  *	    that of the COMMAND, since the other 32-bit words will follow along
98  *	    at the correct addresses.
99  */
100 
101 #define SJA1105_SIZE_DYN_CMD					4
102 
103 #define SJA1105ET_SIZE_VL_LOOKUP_DYN_CMD			\
104 	SJA1105_SIZE_DYN_CMD
105 
106 #define SJA1105PQRS_SIZE_VL_LOOKUP_DYN_CMD			\
107 	(SJA1105_SIZE_DYN_CMD + SJA1105_SIZE_VL_LOOKUP_ENTRY)
108 
109 #define SJA1110_SIZE_VL_POLICING_DYN_CMD			\
110 	(SJA1105_SIZE_DYN_CMD + SJA1105_SIZE_VL_POLICING_ENTRY)
111 
112 #define SJA1105ET_SIZE_MAC_CONFIG_DYN_ENTRY			\
113 	SJA1105_SIZE_DYN_CMD
114 
115 #define SJA1105ET_SIZE_L2_LOOKUP_DYN_CMD			\
116 	(SJA1105_SIZE_DYN_CMD + SJA1105ET_SIZE_L2_LOOKUP_ENTRY)
117 
118 #define SJA1105PQRS_SIZE_L2_LOOKUP_DYN_CMD			\
119 	(SJA1105_SIZE_DYN_CMD + SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY)
120 
121 #define SJA1110_SIZE_L2_LOOKUP_DYN_CMD				\
122 	(SJA1105_SIZE_DYN_CMD + SJA1110_SIZE_L2_LOOKUP_ENTRY)
123 
124 #define SJA1105_SIZE_VLAN_LOOKUP_DYN_CMD			\
125 	(SJA1105_SIZE_DYN_CMD + 4 + SJA1105_SIZE_VLAN_LOOKUP_ENTRY)
126 
127 #define SJA1110_SIZE_VLAN_LOOKUP_DYN_CMD			\
128 	(SJA1105_SIZE_DYN_CMD + SJA1110_SIZE_VLAN_LOOKUP_ENTRY)
129 
130 #define SJA1105_SIZE_L2_FORWARDING_DYN_CMD			\
131 	(SJA1105_SIZE_DYN_CMD + SJA1105_SIZE_L2_FORWARDING_ENTRY)
132 
133 #define SJA1105ET_SIZE_MAC_CONFIG_DYN_CMD			\
134 	(SJA1105_SIZE_DYN_CMD + SJA1105ET_SIZE_MAC_CONFIG_DYN_ENTRY)
135 
136 #define SJA1105PQRS_SIZE_MAC_CONFIG_DYN_CMD			\
137 	(SJA1105_SIZE_DYN_CMD + SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY)
138 
139 #define SJA1105ET_SIZE_L2_LOOKUP_PARAMS_DYN_CMD			\
140 	SJA1105_SIZE_DYN_CMD
141 
142 #define SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_DYN_CMD		\
143 	(SJA1105_SIZE_DYN_CMD + SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_ENTRY)
144 
145 #define SJA1110_SIZE_L2_LOOKUP_PARAMS_DYN_CMD		\
146 	(SJA1105_SIZE_DYN_CMD + SJA1110_SIZE_L2_LOOKUP_PARAMS_ENTRY)
147 
148 #define SJA1105ET_SIZE_GENERAL_PARAMS_DYN_CMD			\
149 	SJA1105_SIZE_DYN_CMD
150 
151 #define SJA1105PQRS_SIZE_GENERAL_PARAMS_DYN_CMD			\
152 	(SJA1105_SIZE_DYN_CMD + SJA1105PQRS_SIZE_GENERAL_PARAMS_ENTRY)
153 
154 #define SJA1110_SIZE_GENERAL_PARAMS_DYN_CMD			\
155 	(SJA1105_SIZE_DYN_CMD + SJA1110_SIZE_GENERAL_PARAMS_ENTRY)
156 
157 #define SJA1105PQRS_SIZE_AVB_PARAMS_DYN_CMD			\
158 	(SJA1105_SIZE_DYN_CMD + SJA1105PQRS_SIZE_AVB_PARAMS_ENTRY)
159 
160 #define SJA1105_SIZE_RETAGGING_DYN_CMD				\
161 	(SJA1105_SIZE_DYN_CMD + SJA1105_SIZE_RETAGGING_ENTRY)
162 
163 #define SJA1105ET_SIZE_CBS_DYN_CMD				\
164 	(SJA1105_SIZE_DYN_CMD + SJA1105ET_SIZE_CBS_ENTRY)
165 
166 #define SJA1105PQRS_SIZE_CBS_DYN_CMD				\
167 	(SJA1105_SIZE_DYN_CMD + SJA1105PQRS_SIZE_CBS_ENTRY)
168 
169 #define SJA1110_SIZE_XMII_PARAMS_DYN_CMD			\
170 	SJA1110_SIZE_XMII_PARAMS_ENTRY
171 
172 #define SJA1110_SIZE_L2_POLICING_DYN_CMD			\
173 	(SJA1105_SIZE_DYN_CMD + SJA1105_SIZE_L2_POLICING_ENTRY)
174 
175 #define SJA1110_SIZE_L2_FORWARDING_PARAMS_DYN_CMD		\
176 	SJA1105_SIZE_L2_FORWARDING_PARAMS_ENTRY
177 
178 #define SJA1105_MAX_DYN_CMD_SIZE				\
179 	SJA1110_SIZE_GENERAL_PARAMS_DYN_CMD
180 
181 struct sja1105_dyn_cmd {
182 	bool search;
183 	u64 valid;
184 	u64 rdwrset;
185 	u64 errors;
186 	u64 valident;
187 	u64 index;
188 };
189 
190 enum sja1105_hostcmd {
191 	SJA1105_HOSTCMD_SEARCH = 1,
192 	SJA1105_HOSTCMD_READ = 2,
193 	SJA1105_HOSTCMD_WRITE = 3,
194 	SJA1105_HOSTCMD_INVALIDATE = 4,
195 };
196 
197 /* Command and entry overlap */
198 static void
199 sja1105et_vl_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
200 				enum packing_op op)
201 {
202 	const int size = SJA1105_SIZE_DYN_CMD;
203 
204 	sja1105_packing(buf, &cmd->valid,   31, 31, size, op);
205 	sja1105_packing(buf, &cmd->errors,  30, 30, size, op);
206 	sja1105_packing(buf, &cmd->rdwrset, 29, 29, size, op);
207 	sja1105_packing(buf, &cmd->index,    9,  0, size, op);
208 }
209 
210 /* Command and entry are separate */
211 static void
212 sja1105pqrs_vl_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
213 				  enum packing_op op)
214 {
215 	u8 *p = buf + SJA1105_SIZE_VL_LOOKUP_ENTRY;
216 	const int size = SJA1105_SIZE_DYN_CMD;
217 
218 	sja1105_packing(p, &cmd->valid,   31, 31, size, op);
219 	sja1105_packing(p, &cmd->errors,  30, 30, size, op);
220 	sja1105_packing(p, &cmd->rdwrset, 29, 29, size, op);
221 	sja1105_packing(p, &cmd->index,    9,  0, size, op);
222 }
223 
224 static void
225 sja1110_vl_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
226 			      enum packing_op op)
227 {
228 	u8 *p = buf + SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY;
229 	const int size = SJA1105_SIZE_DYN_CMD;
230 
231 	sja1105_packing(p, &cmd->valid,   31, 31, size, op);
232 	sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op);
233 	sja1105_packing(p, &cmd->errors,  29, 29, size, op);
234 	sja1105_packing(p, &cmd->index,   11,  0, size, op);
235 }
236 
237 static size_t sja1105et_vl_lookup_entry_packing(void *buf, void *entry_ptr,
238 						enum packing_op op)
239 {
240 	struct sja1105_vl_lookup_entry *entry = entry_ptr;
241 	const int size = SJA1105ET_SIZE_VL_LOOKUP_DYN_CMD;
242 
243 	sja1105_packing(buf, &entry->egrmirr,  21, 17, size, op);
244 	sja1105_packing(buf, &entry->ingrmirr, 16, 16, size, op);
245 	return size;
246 }
247 
248 static void
249 sja1110_vl_policing_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
250 				enum packing_op op)
251 {
252 	u8 *p = buf + SJA1105_SIZE_VL_LOOKUP_ENTRY;
253 	const int size = SJA1105_SIZE_DYN_CMD;
254 
255 	sja1105_packing(p, &cmd->valid,   31, 31, size, op);
256 	sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op);
257 	sja1105_packing(p, &cmd->index,   11,  0, size, op);
258 }
259 
260 static void
261 sja1105pqrs_common_l2_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
262 					 enum packing_op op, int entry_size)
263 {
264 	const int size = SJA1105_SIZE_DYN_CMD;
265 	u8 *p = buf + entry_size;
266 	u64 hostcmd;
267 
268 	sja1105_packing(p, &cmd->valid,    31, 31, size, op);
269 	sja1105_packing(p, &cmd->rdwrset,  30, 30, size, op);
270 	sja1105_packing(p, &cmd->errors,   29, 29, size, op);
271 	sja1105_packing(p, &cmd->valident, 27, 27, size, op);
272 
273 	/* VALIDENT is supposed to indicate "keep or not", but in SJA1105 E/T,
274 	 * using it to delete a management route was unsupported. UM10944
275 	 * said about it:
276 	 *
277 	 *   In case of a write access with the MGMTROUTE flag set,
278 	 *   the flag will be ignored. It will always be found cleared
279 	 *   for read accesses with the MGMTROUTE flag set.
280 	 *
281 	 * SJA1105 P/Q/R/S keeps the same behavior w.r.t. VALIDENT, but there
282 	 * is now another flag called HOSTCMD which does more stuff (quoting
283 	 * from UM11040):
284 	 *
285 	 *   A write request is accepted only when HOSTCMD is set to write host
286 	 *   or invalid. A read request is accepted only when HOSTCMD is set to
287 	 *   search host or read host.
288 	 *
289 	 * So it is possible to translate a RDWRSET/VALIDENT combination into
290 	 * HOSTCMD so that we keep the dynamic command API in place, and
291 	 * at the same time achieve compatibility with the management route
292 	 * command structure.
293 	 */
294 	if (cmd->rdwrset == SPI_READ) {
295 		if (cmd->search)
296 			hostcmd = SJA1105_HOSTCMD_SEARCH;
297 		else
298 			hostcmd = SJA1105_HOSTCMD_READ;
299 	} else {
300 		/* SPI_WRITE */
301 		if (cmd->valident)
302 			hostcmd = SJA1105_HOSTCMD_WRITE;
303 		else
304 			hostcmd = SJA1105_HOSTCMD_INVALIDATE;
305 	}
306 	sja1105_packing(p, &hostcmd, 25, 23, size, op);
307 
308 	/* Hack - The hardware takes the 'index' field within
309 	 * struct sja1105_l2_lookup_entry as the index on which this command
310 	 * will operate. However it will ignore everything else, so 'index'
311 	 * is logically part of command but physically part of entry.
312 	 * Populate the 'index' entry field from within the command callback,
313 	 * such that our API doesn't need to ask for a full-blown entry
314 	 * structure when e.g. a delete is requested.
315 	 */
316 	sja1105_packing(buf, &cmd->index, 15, 6,
317 			SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY, op);
318 }
319 
320 static void
321 sja1105pqrs_l2_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
322 				  enum packing_op op)
323 {
324 	int size = SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY;
325 
326 	return sja1105pqrs_common_l2_lookup_cmd_packing(buf, cmd, op, size);
327 }
328 
329 static void
330 sja1110_l2_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
331 			      enum packing_op op)
332 {
333 	int size = SJA1110_SIZE_L2_LOOKUP_ENTRY;
334 
335 	return sja1105pqrs_common_l2_lookup_cmd_packing(buf, cmd, op, size);
336 }
337 
338 /* The switch is so retarded that it makes our command/entry abstraction
339  * crumble apart.
340  *
341  * On P/Q/R/S, the switch tries to say whether a FDB entry
342  * is statically programmed or dynamically learned via a flag called LOCKEDS.
343  * The hardware manual says about this fiels:
344  *
345  *   On write will specify the format of ENTRY.
346  *   On read the flag will be found cleared at times the VALID flag is found
347  *   set.  The flag will also be found cleared in response to a read having the
348  *   MGMTROUTE flag set.  In response to a read with the MGMTROUTE flag
349  *   cleared, the flag be set if the most recent access operated on an entry
350  *   that was either loaded by configuration or through dynamic reconfiguration
351  *   (as opposed to automatically learned entries).
352  *
353  * The trouble with this flag is that it's part of the *command* to access the
354  * dynamic interface, and not part of the *entry* retrieved from it.
355  * Otherwise said, for a sja1105_dynamic_config_read, LOCKEDS is supposed to be
356  * an output from the switch into the command buffer, and for a
357  * sja1105_dynamic_config_write, the switch treats LOCKEDS as an input
358  * (hence we can write either static, or automatically learned entries, from
359  * the core).
360  * But the manual contradicts itself in the last phrase where it says that on
361  * read, LOCKEDS will be set to 1 for all FDB entries written through the
362  * dynamic interface (therefore, the value of LOCKEDS from the
363  * sja1105_dynamic_config_write is not really used for anything, it'll store a
364  * 1 anyway).
365  * This means you can't really write a FDB entry with LOCKEDS=0 (automatically
366  * learned) into the switch, which kind of makes sense.
367  * As for reading through the dynamic interface, it doesn't make too much sense
368  * to put LOCKEDS into the command, since the switch will inevitably have to
369  * ignore it (otherwise a command would be like "read the FDB entry 123, but
370  * only if it's dynamically learned" <- well how am I supposed to know?) and
371  * just use it as an output buffer for its findings. But guess what... that's
372  * what the entry buffer is for!
373  * Unfortunately, what really breaks this abstraction is the fact that it
374  * wasn't designed having the fact in mind that the switch can output
375  * entry-related data as writeback through the command buffer.
376  * However, whether a FDB entry is statically or dynamically learned *is* part
377  * of the entry and not the command data, no matter what the switch thinks.
378  * In order to do that, we'll need to wrap around the
379  * sja1105pqrs_l2_lookup_entry_packing from sja1105_static_config.c, and take
380  * a peek outside of the caller-supplied @buf (the entry buffer), to reach the
381  * command buffer.
382  */
383 static size_t
384 sja1105pqrs_dyn_l2_lookup_entry_packing(void *buf, void *entry_ptr,
385 					enum packing_op op)
386 {
387 	struct sja1105_l2_lookup_entry *entry = entry_ptr;
388 	u8 *cmd = buf + SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY;
389 	const int size = SJA1105_SIZE_DYN_CMD;
390 
391 	sja1105_packing(cmd, &entry->lockeds, 28, 28, size, op);
392 
393 	return sja1105pqrs_l2_lookup_entry_packing(buf, entry_ptr, op);
394 }
395 
396 static size_t sja1110_dyn_l2_lookup_entry_packing(void *buf, void *entry_ptr,
397 						  enum packing_op op)
398 {
399 	struct sja1105_l2_lookup_entry *entry = entry_ptr;
400 	u8 *cmd = buf + SJA1110_SIZE_L2_LOOKUP_ENTRY;
401 	const int size = SJA1105_SIZE_DYN_CMD;
402 
403 	sja1105_packing(cmd, &entry->lockeds, 28, 28, size, op);
404 
405 	return sja1110_l2_lookup_entry_packing(buf, entry_ptr, op);
406 }
407 
408 static void
409 sja1105et_l2_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
410 				enum packing_op op)
411 {
412 	u8 *p = buf + SJA1105ET_SIZE_L2_LOOKUP_ENTRY;
413 	const int size = SJA1105_SIZE_DYN_CMD;
414 
415 	sja1105_packing(p, &cmd->valid,    31, 31, size, op);
416 	sja1105_packing(p, &cmd->rdwrset,  30, 30, size, op);
417 	sja1105_packing(p, &cmd->errors,   29, 29, size, op);
418 	sja1105_packing(p, &cmd->valident, 27, 27, size, op);
419 	/* Hack - see comments above. */
420 	sja1105_packing(buf, &cmd->index, 29, 20,
421 			SJA1105ET_SIZE_L2_LOOKUP_ENTRY, op);
422 }
423 
424 static size_t sja1105et_dyn_l2_lookup_entry_packing(void *buf, void *entry_ptr,
425 						    enum packing_op op)
426 {
427 	struct sja1105_l2_lookup_entry *entry = entry_ptr;
428 	u8 *cmd = buf + SJA1105ET_SIZE_L2_LOOKUP_ENTRY;
429 	const int size = SJA1105_SIZE_DYN_CMD;
430 
431 	sja1105_packing(cmd, &entry->lockeds, 28, 28, size, op);
432 
433 	return sja1105et_l2_lookup_entry_packing(buf, entry_ptr, op);
434 }
435 
436 static void
437 sja1105et_mgmt_route_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
438 				 enum packing_op op)
439 {
440 	u8 *p = buf + SJA1105ET_SIZE_L2_LOOKUP_ENTRY;
441 	u64 mgmtroute = 1;
442 
443 	sja1105et_l2_lookup_cmd_packing(buf, cmd, op);
444 	if (op == PACK)
445 		sja1105_pack(p, &mgmtroute, 26, 26, SJA1105_SIZE_DYN_CMD);
446 }
447 
448 static size_t sja1105et_mgmt_route_entry_packing(void *buf, void *entry_ptr,
449 						 enum packing_op op)
450 {
451 	struct sja1105_mgmt_entry *entry = entry_ptr;
452 	const size_t size = SJA1105ET_SIZE_L2_LOOKUP_ENTRY;
453 
454 	/* UM10944: To specify if a PTP egress timestamp shall be captured on
455 	 * each port upon transmission of the frame, the LSB of VLANID in the
456 	 * ENTRY field provided by the host must be set.
457 	 * Bit 1 of VLANID then specifies the register where the timestamp for
458 	 * this port is stored in.
459 	 */
460 	sja1105_packing(buf, &entry->tsreg,     85, 85, size, op);
461 	sja1105_packing(buf, &entry->takets,    84, 84, size, op);
462 	sja1105_packing(buf, &entry->macaddr,   83, 36, size, op);
463 	sja1105_packing(buf, &entry->destports, 35, 31, size, op);
464 	sja1105_packing(buf, &entry->enfport,   30, 30, size, op);
465 	return size;
466 }
467 
468 static void
469 sja1105pqrs_mgmt_route_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
470 				   enum packing_op op)
471 {
472 	u8 *p = buf + SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY;
473 	u64 mgmtroute = 1;
474 
475 	sja1105pqrs_l2_lookup_cmd_packing(buf, cmd, op);
476 	if (op == PACK)
477 		sja1105_pack(p, &mgmtroute, 26, 26, SJA1105_SIZE_DYN_CMD);
478 }
479 
480 static size_t sja1105pqrs_mgmt_route_entry_packing(void *buf, void *entry_ptr,
481 						   enum packing_op op)
482 {
483 	const size_t size = SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY;
484 	struct sja1105_mgmt_entry *entry = entry_ptr;
485 
486 	/* In P/Q/R/S, enfport got renamed to mgmtvalid, but its purpose
487 	 * is the same (driver uses it to confirm that frame was sent).
488 	 * So just keep the name from E/T.
489 	 */
490 	sja1105_packing(buf, &entry->tsreg,     71, 71, size, op);
491 	sja1105_packing(buf, &entry->takets,    70, 70, size, op);
492 	sja1105_packing(buf, &entry->macaddr,   69, 22, size, op);
493 	sja1105_packing(buf, &entry->destports, 21, 17, size, op);
494 	sja1105_packing(buf, &entry->enfport,   16, 16, size, op);
495 	return size;
496 }
497 
498 /* In E/T, entry is at addresses 0x27-0x28. There is a 4 byte gap at 0x29,
499  * and command is at 0x2a. Similarly in P/Q/R/S there is a 1 register gap
500  * between entry (0x2d, 0x2e) and command (0x30).
501  */
502 static void
503 sja1105_vlan_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
504 				enum packing_op op)
505 {
506 	u8 *p = buf + SJA1105_SIZE_VLAN_LOOKUP_ENTRY + 4;
507 	const int size = SJA1105_SIZE_DYN_CMD;
508 
509 	sja1105_packing(p, &cmd->valid,    31, 31, size, op);
510 	sja1105_packing(p, &cmd->rdwrset,  30, 30, size, op);
511 	sja1105_packing(p, &cmd->valident, 27, 27, size, op);
512 	/* Hack - see comments above, applied for 'vlanid' field of
513 	 * struct sja1105_vlan_lookup_entry.
514 	 */
515 	sja1105_packing(buf, &cmd->index, 38, 27,
516 			SJA1105_SIZE_VLAN_LOOKUP_ENTRY, op);
517 }
518 
519 /* In SJA1110 there is no gap between the command and the data, yay... */
520 static void
521 sja1110_vlan_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
522 				enum packing_op op)
523 {
524 	u8 *p = buf + SJA1110_SIZE_VLAN_LOOKUP_ENTRY;
525 	const int size = SJA1105_SIZE_DYN_CMD;
526 	u64 type_entry = 0;
527 
528 	sja1105_packing(p, &cmd->valid,   31, 31, size, op);
529 	sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op);
530 	sja1105_packing(p, &cmd->errors,  29, 29, size, op);
531 	/* Hack: treat 'vlanid' field of struct sja1105_vlan_lookup_entry as
532 	 * cmd->index.
533 	 */
534 	sja1105_packing(buf, &cmd->index, 38, 27,
535 			SJA1110_SIZE_VLAN_LOOKUP_ENTRY, op);
536 
537 	/* But the VALIDENT bit has disappeared, now we are supposed to
538 	 * invalidate an entry through the TYPE_ENTRY field of the entry..
539 	 * This is a hack to transform the non-zero quality of the TYPE_ENTRY
540 	 * field into a VALIDENT bit.
541 	 */
542 	if (op == PACK && !cmd->valident) {
543 		sja1105_packing(buf, &type_entry, 40, 39,
544 				SJA1110_SIZE_VLAN_LOOKUP_ENTRY, PACK);
545 	} else if (op == UNPACK) {
546 		sja1105_packing(buf, &type_entry, 40, 39,
547 				SJA1110_SIZE_VLAN_LOOKUP_ENTRY, UNPACK);
548 		cmd->valident = !!type_entry;
549 	}
550 }
551 
552 static void
553 sja1105_l2_forwarding_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
554 				  enum packing_op op)
555 {
556 	u8 *p = buf + SJA1105_SIZE_L2_FORWARDING_ENTRY;
557 	const int size = SJA1105_SIZE_DYN_CMD;
558 
559 	sja1105_packing(p, &cmd->valid,   31, 31, size, op);
560 	sja1105_packing(p, &cmd->errors,  30, 30, size, op);
561 	sja1105_packing(p, &cmd->rdwrset, 29, 29, size, op);
562 	sja1105_packing(p, &cmd->index,    4,  0, size, op);
563 }
564 
565 static void
566 sja1110_l2_forwarding_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
567 				  enum packing_op op)
568 {
569 	u8 *p = buf + SJA1105_SIZE_L2_FORWARDING_ENTRY;
570 	const int size = SJA1105_SIZE_DYN_CMD;
571 
572 	sja1105_packing(p, &cmd->valid,   31, 31, size, op);
573 	sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op);
574 	sja1105_packing(p, &cmd->errors,  29, 29, size, op);
575 	sja1105_packing(p, &cmd->index,    4,  0, size, op);
576 }
577 
578 static void
579 sja1105et_mac_config_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
580 				 enum packing_op op)
581 {
582 	const int size = SJA1105_SIZE_DYN_CMD;
583 	/* Yup, user manual definitions are reversed */
584 	u8 *reg1 = buf + 4;
585 
586 	sja1105_packing(reg1, &cmd->valid, 31, 31, size, op);
587 	sja1105_packing(reg1, &cmd->index, 26, 24, size, op);
588 }
589 
590 static size_t sja1105et_mac_config_entry_packing(void *buf, void *entry_ptr,
591 						 enum packing_op op)
592 {
593 	const int size = SJA1105ET_SIZE_MAC_CONFIG_DYN_ENTRY;
594 	struct sja1105_mac_config_entry *entry = entry_ptr;
595 	/* Yup, user manual definitions are reversed */
596 	u8 *reg1 = buf + 4;
597 	u8 *reg2 = buf;
598 
599 	sja1105_packing(reg1, &entry->speed,     30, 29, size, op);
600 	sja1105_packing(reg1, &entry->drpdtag,   23, 23, size, op);
601 	sja1105_packing(reg1, &entry->drpuntag,  22, 22, size, op);
602 	sja1105_packing(reg1, &entry->retag,     21, 21, size, op);
603 	sja1105_packing(reg1, &entry->dyn_learn, 20, 20, size, op);
604 	sja1105_packing(reg1, &entry->egress,    19, 19, size, op);
605 	sja1105_packing(reg1, &entry->ingress,   18, 18, size, op);
606 	sja1105_packing(reg1, &entry->ing_mirr,  17, 17, size, op);
607 	sja1105_packing(reg1, &entry->egr_mirr,  16, 16, size, op);
608 	sja1105_packing(reg1, &entry->vlanprio,  14, 12, size, op);
609 	sja1105_packing(reg1, &entry->vlanid,    11,  0, size, op);
610 	sja1105_packing(reg2, &entry->tp_delin,  31, 16, size, op);
611 	sja1105_packing(reg2, &entry->tp_delout, 15,  0, size, op);
612 	/* MAC configuration table entries which can't be reconfigured:
613 	 * top, base, enabled, ifg, maxage, drpnona664
614 	 */
615 	/* Bogus return value, not used anywhere */
616 	return 0;
617 }
618 
619 static void
620 sja1105pqrs_mac_config_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
621 				   enum packing_op op)
622 {
623 	const int size = SJA1105ET_SIZE_MAC_CONFIG_DYN_ENTRY;
624 	u8 *p = buf + SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY;
625 
626 	sja1105_packing(p, &cmd->valid,   31, 31, size, op);
627 	sja1105_packing(p, &cmd->errors,  30, 30, size, op);
628 	sja1105_packing(p, &cmd->rdwrset, 29, 29, size, op);
629 	sja1105_packing(p, &cmd->index,    2,  0, size, op);
630 }
631 
632 static void
633 sja1110_mac_config_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
634 			       enum packing_op op)
635 {
636 	u8 *p = buf + SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY;
637 	const int size = SJA1105_SIZE_DYN_CMD;
638 
639 	sja1105_packing(p, &cmd->valid,   31, 31, size, op);
640 	sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op);
641 	sja1105_packing(p, &cmd->errors,  29, 29, size, op);
642 	sja1105_packing(p, &cmd->index,    3,  0, size, op);
643 }
644 
645 static void
646 sja1105et_l2_lookup_params_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
647 				       enum packing_op op)
648 {
649 	sja1105_packing(buf, &cmd->valid, 31, 31,
650 			SJA1105ET_SIZE_L2_LOOKUP_PARAMS_DYN_CMD, op);
651 }
652 
653 static size_t
654 sja1105et_l2_lookup_params_entry_packing(void *buf, void *entry_ptr,
655 					 enum packing_op op)
656 {
657 	struct sja1105_l2_lookup_params_entry *entry = entry_ptr;
658 
659 	sja1105_packing(buf, &entry->poly, 7, 0,
660 			SJA1105ET_SIZE_L2_LOOKUP_PARAMS_DYN_CMD, op);
661 	/* Bogus return value, not used anywhere */
662 	return 0;
663 }
664 
665 static void
666 sja1105pqrs_l2_lookup_params_cmd_packing(void *buf,
667 					 struct sja1105_dyn_cmd *cmd,
668 					 enum packing_op op)
669 {
670 	u8 *p = buf + SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_ENTRY;
671 	const int size = SJA1105_SIZE_DYN_CMD;
672 
673 	sja1105_packing(p, &cmd->valid,   31, 31, size, op);
674 	sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op);
675 }
676 
677 static void
678 sja1110_l2_lookup_params_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
679 				     enum packing_op op)
680 {
681 	u8 *p = buf + SJA1110_SIZE_L2_LOOKUP_PARAMS_ENTRY;
682 	const int size = SJA1105_SIZE_DYN_CMD;
683 
684 	sja1105_packing(p, &cmd->valid,   31, 31, size, op);
685 	sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op);
686 	sja1105_packing(p, &cmd->errors,  29, 29, size, op);
687 }
688 
689 static void
690 sja1105et_general_params_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
691 				     enum packing_op op)
692 {
693 	const int size = SJA1105ET_SIZE_GENERAL_PARAMS_DYN_CMD;
694 
695 	sja1105_packing(buf, &cmd->valid,  31, 31, size, op);
696 	sja1105_packing(buf, &cmd->errors, 30, 30, size, op);
697 }
698 
699 static size_t
700 sja1105et_general_params_entry_packing(void *buf, void *entry_ptr,
701 				       enum packing_op op)
702 {
703 	struct sja1105_general_params_entry *entry = entry_ptr;
704 	const int size = SJA1105ET_SIZE_GENERAL_PARAMS_DYN_CMD;
705 
706 	sja1105_packing(buf, &entry->mirr_port, 2, 0, size, op);
707 	/* Bogus return value, not used anywhere */
708 	return 0;
709 }
710 
711 static void
712 sja1105pqrs_general_params_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
713 				       enum packing_op op)
714 {
715 	u8 *p = buf + SJA1105PQRS_SIZE_GENERAL_PARAMS_ENTRY;
716 	const int size = SJA1105_SIZE_DYN_CMD;
717 
718 	sja1105_packing(p, &cmd->valid,   31, 31, size, op);
719 	sja1105_packing(p, &cmd->errors,  30, 30, size, op);
720 	sja1105_packing(p, &cmd->rdwrset, 28, 28, size, op);
721 }
722 
723 static void
724 sja1110_general_params_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
725 				   enum packing_op op)
726 {
727 	u8 *p = buf + SJA1110_SIZE_GENERAL_PARAMS_ENTRY;
728 	const int size = SJA1105_SIZE_DYN_CMD;
729 
730 	sja1105_packing(p, &cmd->valid,   31, 31, size, op);
731 	sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op);
732 	sja1105_packing(p, &cmd->errors,  29, 29, size, op);
733 }
734 
735 static void
736 sja1105pqrs_avb_params_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
737 				   enum packing_op op)
738 {
739 	u8 *p = buf + SJA1105PQRS_SIZE_AVB_PARAMS_ENTRY;
740 	const int size = SJA1105_SIZE_DYN_CMD;
741 
742 	sja1105_packing(p, &cmd->valid,   31, 31, size, op);
743 	sja1105_packing(p, &cmd->errors,  30, 30, size, op);
744 	sja1105_packing(p, &cmd->rdwrset, 29, 29, size, op);
745 }
746 
747 static void
748 sja1105_retagging_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
749 			      enum packing_op op)
750 {
751 	u8 *p = buf + SJA1105_SIZE_RETAGGING_ENTRY;
752 	const int size = SJA1105_SIZE_DYN_CMD;
753 
754 	sja1105_packing(p, &cmd->valid,    31, 31, size, op);
755 	sja1105_packing(p, &cmd->errors,   30, 30, size, op);
756 	sja1105_packing(p, &cmd->valident, 29, 29, size, op);
757 	sja1105_packing(p, &cmd->rdwrset,  28, 28, size, op);
758 	sja1105_packing(p, &cmd->index,     5,  0, size, op);
759 }
760 
761 static void
762 sja1110_retagging_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
763 			      enum packing_op op)
764 {
765 	u8 *p = buf + SJA1105_SIZE_RETAGGING_ENTRY;
766 	const int size = SJA1105_SIZE_DYN_CMD;
767 
768 	sja1105_packing(p, &cmd->valid,    31, 31, size, op);
769 	sja1105_packing(p, &cmd->rdwrset,  30, 30, size, op);
770 	sja1105_packing(p, &cmd->errors,   29, 29, size, op);
771 	sja1105_packing(p, &cmd->valident, 28, 28, size, op);
772 	sja1105_packing(p, &cmd->index,     4,  0, size, op);
773 }
774 
775 static void sja1105et_cbs_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
776 				      enum packing_op op)
777 {
778 	u8 *p = buf + SJA1105ET_SIZE_CBS_ENTRY;
779 	const int size = SJA1105_SIZE_DYN_CMD;
780 
781 	sja1105_packing(p, &cmd->valid, 31, 31, size, op);
782 	sja1105_packing(p, &cmd->index, 19, 16, size, op);
783 }
784 
785 static size_t sja1105et_cbs_entry_packing(void *buf, void *entry_ptr,
786 					  enum packing_op op)
787 {
788 	const size_t size = SJA1105ET_SIZE_CBS_ENTRY;
789 	struct sja1105_cbs_entry *entry = entry_ptr;
790 	u8 *cmd = buf + size;
791 	u32 *p = buf;
792 
793 	sja1105_packing(cmd, &entry->port, 5, 3, SJA1105_SIZE_DYN_CMD, op);
794 	sja1105_packing(cmd, &entry->prio, 2, 0, SJA1105_SIZE_DYN_CMD, op);
795 	sja1105_packing(p + 3, &entry->credit_lo,  31, 0, size, op);
796 	sja1105_packing(p + 2, &entry->credit_hi,  31, 0, size, op);
797 	sja1105_packing(p + 1, &entry->send_slope, 31, 0, size, op);
798 	sja1105_packing(p + 0, &entry->idle_slope, 31, 0, size, op);
799 	return size;
800 }
801 
802 static void sja1105pqrs_cbs_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
803 					enum packing_op op)
804 {
805 	u8 *p = buf + SJA1105PQRS_SIZE_CBS_ENTRY;
806 	const int size = SJA1105_SIZE_DYN_CMD;
807 
808 	sja1105_packing(p, &cmd->valid,   31, 31, size, op);
809 	sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op);
810 	sja1105_packing(p, &cmd->errors,  29, 29, size, op);
811 	sja1105_packing(p, &cmd->index,    3,  0, size, op);
812 }
813 
814 static void sja1110_cbs_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
815 				    enum packing_op op)
816 {
817 	u8 *p = buf + SJA1105PQRS_SIZE_CBS_ENTRY;
818 	const int size = SJA1105_SIZE_DYN_CMD;
819 
820 	sja1105_packing(p, &cmd->valid,   31, 31, size, op);
821 	sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op);
822 	sja1105_packing(p, &cmd->errors,  29, 29, size, op);
823 	sja1105_packing(p, &cmd->index,    7,  0, size, op);
824 }
825 
826 static size_t sja1105pqrs_cbs_entry_packing(void *buf, void *entry_ptr,
827 					    enum packing_op op)
828 {
829 	const size_t size = SJA1105PQRS_SIZE_CBS_ENTRY;
830 	struct sja1105_cbs_entry *entry = entry_ptr;
831 
832 	sja1105_packing(buf, &entry->port,      159, 157, size, op);
833 	sja1105_packing(buf, &entry->prio,      156, 154, size, op);
834 	sja1105_packing(buf, &entry->credit_lo, 153, 122, size, op);
835 	sja1105_packing(buf, &entry->credit_hi, 121,  90, size, op);
836 	sja1105_packing(buf, &entry->send_slope, 89,  58, size, op);
837 	sja1105_packing(buf, &entry->idle_slope, 57,  26, size, op);
838 	return size;
839 }
840 
841 static size_t sja1110_cbs_entry_packing(void *buf, void *entry_ptr,
842 					enum packing_op op)
843 {
844 	const size_t size = SJA1105PQRS_SIZE_CBS_ENTRY;
845 	struct sja1105_cbs_entry *entry = entry_ptr;
846 	u64 entry_type = SJA1110_CBS_SHAPER;
847 
848 	sja1105_packing(buf, &entry_type,       159, 159, size, op);
849 	sja1105_packing(buf, &entry->credit_lo, 151, 120, size, op);
850 	sja1105_packing(buf, &entry->credit_hi, 119,  88, size, op);
851 	sja1105_packing(buf, &entry->send_slope, 87,  56, size, op);
852 	sja1105_packing(buf, &entry->idle_slope, 55,  24, size, op);
853 	return size;
854 }
855 
856 static void sja1110_dummy_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
857 				      enum packing_op op)
858 {
859 }
860 
861 static void
862 sja1110_l2_policing_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
863 				enum packing_op op)
864 {
865 	u8 *p = buf + SJA1105_SIZE_L2_POLICING_ENTRY;
866 	const int size = SJA1105_SIZE_DYN_CMD;
867 
868 	sja1105_packing(p, &cmd->valid,   31, 31, size, op);
869 	sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op);
870 	sja1105_packing(p, &cmd->errors,  29, 29, size, op);
871 	sja1105_packing(p, &cmd->index,    6,  0, size, op);
872 }
873 
874 #define OP_READ		BIT(0)
875 #define OP_WRITE	BIT(1)
876 #define OP_DEL		BIT(2)
877 #define OP_SEARCH	BIT(3)
878 #define OP_VALID_ANYWAY	BIT(4)
879 
880 /* SJA1105E/T: First generation */
881 const struct sja1105_dynamic_table_ops sja1105et_dyn_ops[BLK_IDX_MAX_DYN] = {
882 	[BLK_IDX_VL_LOOKUP] = {
883 		.entry_packing = sja1105et_vl_lookup_entry_packing,
884 		.cmd_packing = sja1105et_vl_lookup_cmd_packing,
885 		.access = OP_WRITE,
886 		.max_entry_count = SJA1105_MAX_VL_LOOKUP_COUNT,
887 		.packed_size = SJA1105ET_SIZE_VL_LOOKUP_DYN_CMD,
888 		.addr = 0x35,
889 	},
890 	[BLK_IDX_L2_LOOKUP] = {
891 		.entry_packing = sja1105et_dyn_l2_lookup_entry_packing,
892 		.cmd_packing = sja1105et_l2_lookup_cmd_packing,
893 		.access = (OP_READ | OP_WRITE | OP_DEL),
894 		.max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT,
895 		.packed_size = SJA1105ET_SIZE_L2_LOOKUP_DYN_CMD,
896 		.addr = 0x20,
897 	},
898 	[BLK_IDX_MGMT_ROUTE] = {
899 		.entry_packing = sja1105et_mgmt_route_entry_packing,
900 		.cmd_packing = sja1105et_mgmt_route_cmd_packing,
901 		.access = (OP_READ | OP_WRITE | OP_VALID_ANYWAY),
902 		.max_entry_count = SJA1105_NUM_PORTS,
903 		.packed_size = SJA1105ET_SIZE_L2_LOOKUP_DYN_CMD,
904 		.addr = 0x20,
905 	},
906 	[BLK_IDX_VLAN_LOOKUP] = {
907 		.entry_packing = sja1105_vlan_lookup_entry_packing,
908 		.cmd_packing = sja1105_vlan_lookup_cmd_packing,
909 		.access = (OP_WRITE | OP_DEL),
910 		.max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT,
911 		.packed_size = SJA1105_SIZE_VLAN_LOOKUP_DYN_CMD,
912 		.addr = 0x27,
913 	},
914 	[BLK_IDX_L2_FORWARDING] = {
915 		.entry_packing = sja1105_l2_forwarding_entry_packing,
916 		.cmd_packing = sja1105_l2_forwarding_cmd_packing,
917 		.max_entry_count = SJA1105_MAX_L2_FORWARDING_COUNT,
918 		.access = OP_WRITE,
919 		.packed_size = SJA1105_SIZE_L2_FORWARDING_DYN_CMD,
920 		.addr = 0x24,
921 	},
922 	[BLK_IDX_MAC_CONFIG] = {
923 		.entry_packing = sja1105et_mac_config_entry_packing,
924 		.cmd_packing = sja1105et_mac_config_cmd_packing,
925 		.max_entry_count = SJA1105_MAX_MAC_CONFIG_COUNT,
926 		.access = OP_WRITE,
927 		.packed_size = SJA1105ET_SIZE_MAC_CONFIG_DYN_CMD,
928 		.addr = 0x36,
929 	},
930 	[BLK_IDX_L2_LOOKUP_PARAMS] = {
931 		.entry_packing = sja1105et_l2_lookup_params_entry_packing,
932 		.cmd_packing = sja1105et_l2_lookup_params_cmd_packing,
933 		.max_entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT,
934 		.access = OP_WRITE,
935 		.packed_size = SJA1105ET_SIZE_L2_LOOKUP_PARAMS_DYN_CMD,
936 		.addr = 0x38,
937 	},
938 	[BLK_IDX_GENERAL_PARAMS] = {
939 		.entry_packing = sja1105et_general_params_entry_packing,
940 		.cmd_packing = sja1105et_general_params_cmd_packing,
941 		.max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT,
942 		.access = OP_WRITE,
943 		.packed_size = SJA1105ET_SIZE_GENERAL_PARAMS_DYN_CMD,
944 		.addr = 0x34,
945 	},
946 	[BLK_IDX_RETAGGING] = {
947 		.entry_packing = sja1105_retagging_entry_packing,
948 		.cmd_packing = sja1105_retagging_cmd_packing,
949 		.max_entry_count = SJA1105_MAX_RETAGGING_COUNT,
950 		.access = (OP_WRITE | OP_DEL),
951 		.packed_size = SJA1105_SIZE_RETAGGING_DYN_CMD,
952 		.addr = 0x31,
953 	},
954 	[BLK_IDX_CBS] = {
955 		.entry_packing = sja1105et_cbs_entry_packing,
956 		.cmd_packing = sja1105et_cbs_cmd_packing,
957 		.max_entry_count = SJA1105ET_MAX_CBS_COUNT,
958 		.access = OP_WRITE,
959 		.packed_size = SJA1105ET_SIZE_CBS_DYN_CMD,
960 		.addr = 0x2c,
961 	},
962 };
963 
964 /* SJA1105P/Q/R/S: Second generation */
965 const struct sja1105_dynamic_table_ops sja1105pqrs_dyn_ops[BLK_IDX_MAX_DYN] = {
966 	[BLK_IDX_VL_LOOKUP] = {
967 		.entry_packing = sja1105_vl_lookup_entry_packing,
968 		.cmd_packing = sja1105pqrs_vl_lookup_cmd_packing,
969 		.access = (OP_READ | OP_WRITE),
970 		.max_entry_count = SJA1105_MAX_VL_LOOKUP_COUNT,
971 		.packed_size = SJA1105PQRS_SIZE_VL_LOOKUP_DYN_CMD,
972 		.addr = 0x47,
973 	},
974 	[BLK_IDX_L2_LOOKUP] = {
975 		.entry_packing = sja1105pqrs_dyn_l2_lookup_entry_packing,
976 		.cmd_packing = sja1105pqrs_l2_lookup_cmd_packing,
977 		.access = (OP_READ | OP_WRITE | OP_DEL | OP_SEARCH),
978 		.max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT,
979 		.packed_size = SJA1105PQRS_SIZE_L2_LOOKUP_DYN_CMD,
980 		.addr = 0x24,
981 	},
982 	[BLK_IDX_MGMT_ROUTE] = {
983 		.entry_packing = sja1105pqrs_mgmt_route_entry_packing,
984 		.cmd_packing = sja1105pqrs_mgmt_route_cmd_packing,
985 		.access = (OP_READ | OP_WRITE | OP_DEL | OP_SEARCH | OP_VALID_ANYWAY),
986 		.max_entry_count = SJA1105_NUM_PORTS,
987 		.packed_size = SJA1105PQRS_SIZE_L2_LOOKUP_DYN_CMD,
988 		.addr = 0x24,
989 	},
990 	[BLK_IDX_VLAN_LOOKUP] = {
991 		.entry_packing = sja1105_vlan_lookup_entry_packing,
992 		.cmd_packing = sja1105_vlan_lookup_cmd_packing,
993 		.access = (OP_READ | OP_WRITE | OP_DEL),
994 		.max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT,
995 		.packed_size = SJA1105_SIZE_VLAN_LOOKUP_DYN_CMD,
996 		.addr = 0x2D,
997 	},
998 	[BLK_IDX_L2_FORWARDING] = {
999 		.entry_packing = sja1105_l2_forwarding_entry_packing,
1000 		.cmd_packing = sja1105_l2_forwarding_cmd_packing,
1001 		.max_entry_count = SJA1105_MAX_L2_FORWARDING_COUNT,
1002 		.access = OP_WRITE,
1003 		.packed_size = SJA1105_SIZE_L2_FORWARDING_DYN_CMD,
1004 		.addr = 0x2A,
1005 	},
1006 	[BLK_IDX_MAC_CONFIG] = {
1007 		.entry_packing = sja1105pqrs_mac_config_entry_packing,
1008 		.cmd_packing = sja1105pqrs_mac_config_cmd_packing,
1009 		.max_entry_count = SJA1105_MAX_MAC_CONFIG_COUNT,
1010 		.access = (OP_READ | OP_WRITE),
1011 		.packed_size = SJA1105PQRS_SIZE_MAC_CONFIG_DYN_CMD,
1012 		.addr = 0x4B,
1013 	},
1014 	[BLK_IDX_L2_LOOKUP_PARAMS] = {
1015 		.entry_packing = sja1105pqrs_l2_lookup_params_entry_packing,
1016 		.cmd_packing = sja1105pqrs_l2_lookup_params_cmd_packing,
1017 		.max_entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT,
1018 		.access = (OP_READ | OP_WRITE),
1019 		.packed_size = SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_DYN_CMD,
1020 		.addr = 0x54,
1021 	},
1022 	[BLK_IDX_AVB_PARAMS] = {
1023 		.entry_packing = sja1105pqrs_avb_params_entry_packing,
1024 		.cmd_packing = sja1105pqrs_avb_params_cmd_packing,
1025 		.max_entry_count = SJA1105_MAX_AVB_PARAMS_COUNT,
1026 		.access = (OP_READ | OP_WRITE),
1027 		.packed_size = SJA1105PQRS_SIZE_AVB_PARAMS_DYN_CMD,
1028 		.addr = 0x8003,
1029 	},
1030 	[BLK_IDX_GENERAL_PARAMS] = {
1031 		.entry_packing = sja1105pqrs_general_params_entry_packing,
1032 		.cmd_packing = sja1105pqrs_general_params_cmd_packing,
1033 		.max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT,
1034 		.access = (OP_READ | OP_WRITE),
1035 		.packed_size = SJA1105PQRS_SIZE_GENERAL_PARAMS_DYN_CMD,
1036 		.addr = 0x3B,
1037 	},
1038 	[BLK_IDX_RETAGGING] = {
1039 		.entry_packing = sja1105_retagging_entry_packing,
1040 		.cmd_packing = sja1105_retagging_cmd_packing,
1041 		.max_entry_count = SJA1105_MAX_RETAGGING_COUNT,
1042 		.access = (OP_READ | OP_WRITE | OP_DEL),
1043 		.packed_size = SJA1105_SIZE_RETAGGING_DYN_CMD,
1044 		.addr = 0x38,
1045 	},
1046 	[BLK_IDX_CBS] = {
1047 		.entry_packing = sja1105pqrs_cbs_entry_packing,
1048 		.cmd_packing = sja1105pqrs_cbs_cmd_packing,
1049 		.max_entry_count = SJA1105PQRS_MAX_CBS_COUNT,
1050 		.access = OP_WRITE,
1051 		.packed_size = SJA1105PQRS_SIZE_CBS_DYN_CMD,
1052 		.addr = 0x32,
1053 	},
1054 };
1055 
1056 /* SJA1110: Third generation */
1057 const struct sja1105_dynamic_table_ops sja1110_dyn_ops[BLK_IDX_MAX_DYN] = {
1058 	[BLK_IDX_VL_LOOKUP] = {
1059 		.entry_packing = sja1110_vl_lookup_entry_packing,
1060 		.cmd_packing = sja1110_vl_lookup_cmd_packing,
1061 		.access = (OP_READ | OP_WRITE | OP_VALID_ANYWAY),
1062 		.max_entry_count = SJA1110_MAX_VL_LOOKUP_COUNT,
1063 		.packed_size = SJA1105PQRS_SIZE_VL_LOOKUP_DYN_CMD,
1064 		.addr = SJA1110_SPI_ADDR(0x124),
1065 	},
1066 	[BLK_IDX_VL_POLICING] = {
1067 		.entry_packing = sja1110_vl_policing_entry_packing,
1068 		.cmd_packing = sja1110_vl_policing_cmd_packing,
1069 		.access = (OP_READ | OP_WRITE | OP_VALID_ANYWAY),
1070 		.max_entry_count = SJA1110_MAX_VL_POLICING_COUNT,
1071 		.packed_size = SJA1110_SIZE_VL_POLICING_DYN_CMD,
1072 		.addr = SJA1110_SPI_ADDR(0x310),
1073 	},
1074 	[BLK_IDX_L2_LOOKUP] = {
1075 		.entry_packing = sja1110_dyn_l2_lookup_entry_packing,
1076 		.cmd_packing = sja1110_l2_lookup_cmd_packing,
1077 		.access = (OP_READ | OP_WRITE | OP_DEL | OP_SEARCH),
1078 		.max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT,
1079 		.packed_size = SJA1110_SIZE_L2_LOOKUP_DYN_CMD,
1080 		.addr = SJA1110_SPI_ADDR(0x8c),
1081 	},
1082 	[BLK_IDX_VLAN_LOOKUP] = {
1083 		.entry_packing = sja1110_vlan_lookup_entry_packing,
1084 		.cmd_packing = sja1110_vlan_lookup_cmd_packing,
1085 		.access = (OP_READ | OP_WRITE | OP_DEL),
1086 		.max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT,
1087 		.packed_size = SJA1110_SIZE_VLAN_LOOKUP_DYN_CMD,
1088 		.addr = SJA1110_SPI_ADDR(0xb4),
1089 	},
1090 	[BLK_IDX_L2_FORWARDING] = {
1091 		.entry_packing = sja1110_l2_forwarding_entry_packing,
1092 		.cmd_packing = sja1110_l2_forwarding_cmd_packing,
1093 		.max_entry_count = SJA1110_MAX_L2_FORWARDING_COUNT,
1094 		.access = (OP_READ | OP_WRITE | OP_VALID_ANYWAY),
1095 		.packed_size = SJA1105_SIZE_L2_FORWARDING_DYN_CMD,
1096 		.addr = SJA1110_SPI_ADDR(0xa8),
1097 	},
1098 	[BLK_IDX_MAC_CONFIG] = {
1099 		.entry_packing = sja1110_mac_config_entry_packing,
1100 		.cmd_packing = sja1110_mac_config_cmd_packing,
1101 		.max_entry_count = SJA1110_MAX_MAC_CONFIG_COUNT,
1102 		.access = (OP_READ | OP_WRITE | OP_VALID_ANYWAY),
1103 		.packed_size = SJA1105PQRS_SIZE_MAC_CONFIG_DYN_CMD,
1104 		.addr = SJA1110_SPI_ADDR(0x134),
1105 	},
1106 	[BLK_IDX_L2_LOOKUP_PARAMS] = {
1107 		.entry_packing = sja1110_l2_lookup_params_entry_packing,
1108 		.cmd_packing = sja1110_l2_lookup_params_cmd_packing,
1109 		.max_entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT,
1110 		.access = (OP_READ | OP_WRITE | OP_VALID_ANYWAY),
1111 		.packed_size = SJA1110_SIZE_L2_LOOKUP_PARAMS_DYN_CMD,
1112 		.addr = SJA1110_SPI_ADDR(0x158),
1113 	},
1114 	[BLK_IDX_AVB_PARAMS] = {
1115 		.entry_packing = sja1105pqrs_avb_params_entry_packing,
1116 		.cmd_packing = sja1105pqrs_avb_params_cmd_packing,
1117 		.max_entry_count = SJA1105_MAX_AVB_PARAMS_COUNT,
1118 		.access = (OP_READ | OP_WRITE | OP_VALID_ANYWAY),
1119 		.packed_size = SJA1105PQRS_SIZE_AVB_PARAMS_DYN_CMD,
1120 		.addr = SJA1110_SPI_ADDR(0x2000C),
1121 	},
1122 	[BLK_IDX_GENERAL_PARAMS] = {
1123 		.entry_packing = sja1110_general_params_entry_packing,
1124 		.cmd_packing = sja1110_general_params_cmd_packing,
1125 		.max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT,
1126 		.access = (OP_READ | OP_WRITE | OP_VALID_ANYWAY),
1127 		.packed_size = SJA1110_SIZE_GENERAL_PARAMS_DYN_CMD,
1128 		.addr = SJA1110_SPI_ADDR(0xe8),
1129 	},
1130 	[BLK_IDX_RETAGGING] = {
1131 		.entry_packing = sja1110_retagging_entry_packing,
1132 		.cmd_packing = sja1110_retagging_cmd_packing,
1133 		.max_entry_count = SJA1105_MAX_RETAGGING_COUNT,
1134 		.access = (OP_READ | OP_WRITE | OP_DEL),
1135 		.packed_size = SJA1105_SIZE_RETAGGING_DYN_CMD,
1136 		.addr = SJA1110_SPI_ADDR(0xdc),
1137 	},
1138 	[BLK_IDX_CBS] = {
1139 		.entry_packing = sja1110_cbs_entry_packing,
1140 		.cmd_packing = sja1110_cbs_cmd_packing,
1141 		.max_entry_count = SJA1110_MAX_CBS_COUNT,
1142 		.access = (OP_READ | OP_WRITE | OP_VALID_ANYWAY),
1143 		.packed_size = SJA1105PQRS_SIZE_CBS_DYN_CMD,
1144 		.addr = SJA1110_SPI_ADDR(0xc4),
1145 	},
1146 	[BLK_IDX_XMII_PARAMS] = {
1147 		.entry_packing = sja1110_xmii_params_entry_packing,
1148 		.cmd_packing = sja1110_dummy_cmd_packing,
1149 		.max_entry_count = SJA1105_MAX_XMII_PARAMS_COUNT,
1150 		.access = (OP_READ | OP_VALID_ANYWAY),
1151 		.packed_size = SJA1110_SIZE_XMII_PARAMS_DYN_CMD,
1152 		.addr = SJA1110_SPI_ADDR(0x3c),
1153 	},
1154 	[BLK_IDX_L2_POLICING] = {
1155 		.entry_packing = sja1110_l2_policing_entry_packing,
1156 		.cmd_packing = sja1110_l2_policing_cmd_packing,
1157 		.max_entry_count = SJA1110_MAX_L2_POLICING_COUNT,
1158 		.access = (OP_READ | OP_WRITE | OP_VALID_ANYWAY),
1159 		.packed_size = SJA1110_SIZE_L2_POLICING_DYN_CMD,
1160 		.addr = SJA1110_SPI_ADDR(0x2fc),
1161 	},
1162 	[BLK_IDX_L2_FORWARDING_PARAMS] = {
1163 		.entry_packing = sja1110_l2_forwarding_params_entry_packing,
1164 		.cmd_packing = sja1110_dummy_cmd_packing,
1165 		.max_entry_count = SJA1105_MAX_L2_FORWARDING_PARAMS_COUNT,
1166 		.access = (OP_READ | OP_VALID_ANYWAY),
1167 		.packed_size = SJA1110_SIZE_L2_FORWARDING_PARAMS_DYN_CMD,
1168 		.addr = SJA1110_SPI_ADDR(0x20000),
1169 	},
1170 };
1171 
1172 /* Provides read access to the settings through the dynamic interface
1173  * of the switch.
1174  * @blk_idx	is used as key to select from the sja1105_dynamic_table_ops.
1175  *		The selection is limited by the hardware in respect to which
1176  *		configuration blocks can be read through the dynamic interface.
1177  * @index	is used to retrieve a particular table entry. If negative,
1178  *		(and if the @blk_idx supports the searching operation) a search
1179  *		is performed by the @entry parameter.
1180  * @entry	Type-casted to an unpacked structure that holds a table entry
1181  *		of the type specified in @blk_idx.
1182  *		Usually an output argument. If @index is negative, then this
1183  *		argument is used as input/output: it should be pre-populated
1184  *		with the element to search for. Entries which support the
1185  *		search operation will have an "index" field (not the @index
1186  *		argument to this function) and that is where the found index
1187  *		will be returned (or left unmodified - thus negative - if not
1188  *		found).
1189  */
1190 int sja1105_dynamic_config_read(struct sja1105_private *priv,
1191 				enum sja1105_blk_idx blk_idx,
1192 				int index, void *entry)
1193 {
1194 	const struct sja1105_dynamic_table_ops *ops;
1195 	struct sja1105_dyn_cmd cmd = {0};
1196 	/* SPI payload buffer */
1197 	u8 packed_buf[SJA1105_MAX_DYN_CMD_SIZE] = {0};
1198 	int retries = 3;
1199 	int rc;
1200 
1201 	if (blk_idx >= BLK_IDX_MAX_DYN)
1202 		return -ERANGE;
1203 
1204 	ops = &priv->info->dyn_ops[blk_idx];
1205 
1206 	if (index >= 0 && index >= ops->max_entry_count)
1207 		return -ERANGE;
1208 	if (index < 0 && !(ops->access & OP_SEARCH))
1209 		return -EOPNOTSUPP;
1210 	if (!(ops->access & OP_READ))
1211 		return -EOPNOTSUPP;
1212 	if (ops->packed_size > SJA1105_MAX_DYN_CMD_SIZE)
1213 		return -ERANGE;
1214 	if (!ops->cmd_packing)
1215 		return -EOPNOTSUPP;
1216 	if (!ops->entry_packing)
1217 		return -EOPNOTSUPP;
1218 
1219 	cmd.valid = true; /* Trigger action on table entry */
1220 	cmd.rdwrset = SPI_READ; /* Action is read */
1221 	if (index < 0) {
1222 		/* Avoid copying a signed negative number to an u64 */
1223 		cmd.index = 0;
1224 		cmd.search = true;
1225 	} else {
1226 		cmd.index = index;
1227 		cmd.search = false;
1228 	}
1229 	cmd.valident = true;
1230 	ops->cmd_packing(packed_buf, &cmd, PACK);
1231 
1232 	if (cmd.search)
1233 		ops->entry_packing(packed_buf, entry, PACK);
1234 
1235 	/* Send SPI write operation: read config table entry */
1236 	rc = sja1105_xfer_buf(priv, SPI_WRITE, ops->addr, packed_buf,
1237 			      ops->packed_size);
1238 	if (rc < 0)
1239 		return rc;
1240 
1241 	/* Loop until we have confirmation that hardware has finished
1242 	 * processing the command and has cleared the VALID field
1243 	 */
1244 	do {
1245 		memset(packed_buf, 0, ops->packed_size);
1246 
1247 		/* Retrieve the read operation's result */
1248 		rc = sja1105_xfer_buf(priv, SPI_READ, ops->addr, packed_buf,
1249 				      ops->packed_size);
1250 		if (rc < 0)
1251 			return rc;
1252 
1253 		cmd = (struct sja1105_dyn_cmd) {0};
1254 		ops->cmd_packing(packed_buf, &cmd, UNPACK);
1255 
1256 		if (!cmd.valident && !(ops->access & OP_VALID_ANYWAY))
1257 			return -ENOENT;
1258 		cpu_relax();
1259 	} while (cmd.valid && --retries);
1260 
1261 	if (cmd.valid)
1262 		return -ETIMEDOUT;
1263 
1264 	/* Don't dereference possibly NULL pointer - maybe caller
1265 	 * only wanted to see whether the entry existed or not.
1266 	 */
1267 	if (entry)
1268 		ops->entry_packing(packed_buf, entry, UNPACK);
1269 	return 0;
1270 }
1271 
1272 int sja1105_dynamic_config_write(struct sja1105_private *priv,
1273 				 enum sja1105_blk_idx blk_idx,
1274 				 int index, void *entry, bool keep)
1275 {
1276 	const struct sja1105_dynamic_table_ops *ops;
1277 	struct sja1105_dyn_cmd cmd = {0};
1278 	/* SPI payload buffer */
1279 	u8 packed_buf[SJA1105_MAX_DYN_CMD_SIZE] = {0};
1280 	int rc;
1281 
1282 	if (blk_idx >= BLK_IDX_MAX_DYN)
1283 		return -ERANGE;
1284 
1285 	ops = &priv->info->dyn_ops[blk_idx];
1286 
1287 	if (index >= ops->max_entry_count)
1288 		return -ERANGE;
1289 	if (index < 0)
1290 		return -ERANGE;
1291 	if (!(ops->access & OP_WRITE))
1292 		return -EOPNOTSUPP;
1293 	if (!keep && !(ops->access & OP_DEL))
1294 		return -EOPNOTSUPP;
1295 	if (ops->packed_size > SJA1105_MAX_DYN_CMD_SIZE)
1296 		return -ERANGE;
1297 
1298 	cmd.valident = keep; /* If false, deletes entry */
1299 	cmd.valid = true; /* Trigger action on table entry */
1300 	cmd.rdwrset = SPI_WRITE; /* Action is write */
1301 	cmd.index = index;
1302 
1303 	if (!ops->cmd_packing)
1304 		return -EOPNOTSUPP;
1305 	ops->cmd_packing(packed_buf, &cmd, PACK);
1306 
1307 	if (!ops->entry_packing)
1308 		return -EOPNOTSUPP;
1309 	/* Don't dereference potentially NULL pointer if just
1310 	 * deleting a table entry is what was requested. For cases
1311 	 * where 'index' field is physically part of entry structure,
1312 	 * and needed here, we deal with that in the cmd_packing callback.
1313 	 */
1314 	if (keep)
1315 		ops->entry_packing(packed_buf, entry, PACK);
1316 
1317 	/* Send SPI write operation: read config table entry */
1318 	rc = sja1105_xfer_buf(priv, SPI_WRITE, ops->addr, packed_buf,
1319 			      ops->packed_size);
1320 	if (rc < 0)
1321 		return rc;
1322 
1323 	cmd = (struct sja1105_dyn_cmd) {0};
1324 	ops->cmd_packing(packed_buf, &cmd, UNPACK);
1325 	if (cmd.errors)
1326 		return -EINVAL;
1327 
1328 	return 0;
1329 }
1330 
1331 static u8 sja1105_crc8_add(u8 crc, u8 byte, u8 poly)
1332 {
1333 	int i;
1334 
1335 	for (i = 0; i < 8; i++) {
1336 		if ((crc ^ byte) & (1 << 7)) {
1337 			crc <<= 1;
1338 			crc ^= poly;
1339 		} else {
1340 			crc <<= 1;
1341 		}
1342 		byte <<= 1;
1343 	}
1344 	return crc;
1345 }
1346 
1347 /* CRC8 algorithm with non-reversed input, non-reversed output,
1348  * no input xor and no output xor. Code customized for receiving
1349  * the SJA1105 E/T FDB keys (vlanid, macaddr) as input. CRC polynomial
1350  * is also received as argument in the Koopman notation that the switch
1351  * hardware stores it in.
1352  */
1353 u8 sja1105et_fdb_hash(struct sja1105_private *priv, const u8 *addr, u16 vid)
1354 {
1355 	struct sja1105_l2_lookup_params_entry *l2_lookup_params =
1356 		priv->static_config.tables[BLK_IDX_L2_LOOKUP_PARAMS].entries;
1357 	u64 poly_koopman = l2_lookup_params->poly;
1358 	/* Convert polynomial from Koopman to 'normal' notation */
1359 	u8 poly = (u8)(1 + (poly_koopman << 1));
1360 	u64 vlanid = l2_lookup_params->shared_learn ? 0 : vid;
1361 	u64 input = (vlanid << 48) | ether_addr_to_u64(addr);
1362 	u8 crc = 0; /* seed */
1363 	int i;
1364 
1365 	/* Mask the eight bytes starting from MSB one at a time */
1366 	for (i = 56; i >= 0; i -= 8) {
1367 		u8 byte = (input & (0xffull << i)) >> i;
1368 
1369 		crc = sja1105_crc8_add(crc, byte, poly);
1370 	}
1371 	return crc;
1372 }
1373