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_SIZE_VL_LOOKUP_DYN_CMD			\
101 	SJA1105_SIZE_DYN_CMD
102 
103 #define SJA1105PQRS_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 
154 struct sja1105_dyn_cmd {
155 	bool search;
156 	u64 valid;
157 	u64 rdwrset;
158 	u64 errors;
159 	u64 valident;
160 	u64 index;
161 };
162 
163 enum sja1105_hostcmd {
164 	SJA1105_HOSTCMD_SEARCH = 1,
165 	SJA1105_HOSTCMD_READ = 2,
166 	SJA1105_HOSTCMD_WRITE = 3,
167 	SJA1105_HOSTCMD_INVALIDATE = 4,
168 };
169 
170 static void
sja1105_vl_lookup_cmd_packing(void * buf,struct sja1105_dyn_cmd * cmd,enum packing_op op)171 sja1105_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 
sja1105et_vl_lookup_entry_packing(void * buf,void * entry_ptr,enum packing_op op)182 static 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_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 
193 static void
sja1105pqrs_l2_lookup_cmd_packing(void * buf,struct sja1105_dyn_cmd * cmd,enum packing_op op)194 sja1105pqrs_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  */
298 static size_t
sja1105pqrs_dyn_l2_lookup_entry_packing(void * buf,void * entry_ptr,enum packing_op op)299 sja1105pqrs_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 
311 static void
sja1105et_l2_lookup_cmd_packing(void * buf,struct sja1105_dyn_cmd * cmd,enum packing_op op)312 sja1105et_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 
sja1105et_dyn_l2_lookup_entry_packing(void * buf,void * entry_ptr,enum packing_op op)327 static 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 
339 static void
sja1105et_mgmt_route_cmd_packing(void * buf,struct sja1105_dyn_cmd * cmd,enum packing_op op)340 sja1105et_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 
sja1105et_mgmt_route_entry_packing(void * buf,void * entry_ptr,enum packing_op op)351 static 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 
371 static void
sja1105pqrs_mgmt_route_cmd_packing(void * buf,struct sja1105_dyn_cmd * cmd,enum packing_op op)372 sja1105pqrs_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 
sja1105pqrs_mgmt_route_entry_packing(void * buf,void * entry_ptr,enum packing_op op)383 static 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  */
405 static void
sja1105_vlan_lookup_cmd_packing(void * buf,struct sja1105_dyn_cmd * cmd,enum packing_op op)406 sja1105_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 
422 static void
sja1105_l2_forwarding_cmd_packing(void * buf,struct sja1105_dyn_cmd * cmd,enum packing_op op)423 sja1105_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 
435 static void
sja1105et_mac_config_cmd_packing(void * buf,struct sja1105_dyn_cmd * cmd,enum packing_op op)436 sja1105et_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 
sja1105et_mac_config_entry_packing(void * buf,void * entry_ptr,enum packing_op op)447 static 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 
476 static void
sja1105pqrs_mac_config_cmd_packing(void * buf,struct sja1105_dyn_cmd * cmd,enum packing_op op)477 sja1105pqrs_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 
489 static void
sja1105et_l2_lookup_params_cmd_packing(void * buf,struct sja1105_dyn_cmd * cmd,enum packing_op op)490 sja1105et_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 
497 static size_t
sja1105et_l2_lookup_params_entry_packing(void * buf,void * entry_ptr,enum packing_op op)498 sja1105et_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 
509 static void
sja1105pqrs_l2_lookup_params_cmd_packing(void * buf,struct sja1105_dyn_cmd * cmd,enum packing_op op)510 sja1105pqrs_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 
521 static void
sja1105et_general_params_cmd_packing(void * buf,struct sja1105_dyn_cmd * cmd,enum packing_op op)522 sja1105et_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 
531 static size_t
sja1105et_general_params_entry_packing(void * buf,void * entry_ptr,enum packing_op op)532 sja1105et_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 
543 static void
sja1105pqrs_general_params_cmd_packing(void * buf,struct sja1105_dyn_cmd * cmd,enum packing_op op)544 sja1105pqrs_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 
555 static void
sja1105pqrs_avb_params_cmd_packing(void * buf,struct sja1105_dyn_cmd * cmd,enum packing_op op)556 sja1105pqrs_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 
567 static void
sja1105_retagging_cmd_packing(void * buf,struct sja1105_dyn_cmd * cmd,enum packing_op op)568 sja1105_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 
sja1105et_cbs_cmd_packing(void * buf,struct sja1105_dyn_cmd * cmd,enum packing_op op)581 static 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 
sja1105et_cbs_entry_packing(void * buf,void * entry_ptr,enum packing_op op)591 static 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 
sja1105pqrs_cbs_cmd_packing(void * buf,struct sja1105_dyn_cmd * cmd,enum packing_op op)608 static 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 
sja1105pqrs_cbs_entry_packing(void * buf,void * entry_ptr,enum packing_op op)620 static 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 */
641 const 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_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 */
725 const 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_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  */
sja1105_dynamic_config_read(struct sja1105_private * priv,enum sja1105_blk_idx blk_idx,int index,void * entry)834 int 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 
sja1105_dynamic_config_write(struct sja1105_private * priv,enum sja1105_blk_idx blk_idx,int index,void * entry,bool keep)919 int 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 
sja1105_crc8_add(u8 crc,u8 byte,u8 poly)978 static 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  */
sja1105et_fdb_hash(struct sja1105_private * priv,const u8 * addr,u16 vid)1000 u8 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 }
1020