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