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