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