1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com> 3 */ 4 #include "sja1105.h" 5 6 /* In the dynamic configuration interface, the switch exposes a register-like 7 * view of some of the static configuration tables. 8 * Many times the field organization of the dynamic tables is abbreviated (not 9 * all fields are dynamically reconfigurable) and different from the static 10 * ones, but the key reason for having it is that we can spare a switch reset 11 * for settings that can be changed dynamically. 12 * 13 * This file creates a per-switch-family abstraction called 14 * struct sja1105_dynamic_table_ops and two operations that work with it: 15 * - sja1105_dynamic_config_write 16 * - sja1105_dynamic_config_read 17 * 18 * Compared to the struct sja1105_table_ops from sja1105_static_config.c, 19 * the dynamic accessors work with a compound buffer: 20 * 21 * packed_buf 22 * 23 * | 24 * V 25 * +-----------------------------------------+------------------+ 26 * | ENTRY BUFFER | COMMAND BUFFER | 27 * +-----------------------------------------+------------------+ 28 * 29 * <----------------------- packed_size ------------------------> 30 * 31 * The ENTRY BUFFER may or may not have the same layout, or size, as its static 32 * configuration table entry counterpart. When it does, the same packing 33 * function is reused (bar exceptional cases - see 34 * sja1105pqrs_dyn_l2_lookup_entry_packing). 35 * 36 * The reason for the COMMAND BUFFER being at the end is to be able to send 37 * a dynamic write command through a single SPI burst. By the time the switch 38 * reacts to the command, the ENTRY BUFFER is already populated with the data 39 * sent by the core. 40 * 41 * The COMMAND BUFFER is always SJA1105_SIZE_DYN_CMD bytes (one 32-bit word) in 42 * size. 43 * 44 * Sometimes the ENTRY BUFFER does not really exist (when the number of fields 45 * that can be reconfigured is small), then the switch repurposes some of the 46 * unused 32 bits of the COMMAND BUFFER to hold ENTRY data. 47 * 48 * The key members of struct sja1105_dynamic_table_ops are: 49 * - .entry_packing: A function that deals with packing an ENTRY structure 50 * into an SPI buffer, or retrieving an ENTRY structure 51 * from one. 52 * The @packed_buf pointer it's given does always point to 53 * the ENTRY portion of the buffer. 54 * - .cmd_packing: A function that deals with packing/unpacking the COMMAND 55 * structure to/from the SPI buffer. 56 * It is given the same @packed_buf pointer as .entry_packing, 57 * so most of the time, the @packed_buf points *behind* the 58 * COMMAND offset inside the buffer. 59 * To access the COMMAND portion of the buffer, the function 60 * knows its correct offset. 61 * Giving both functions the same pointer is handy because in 62 * extreme cases (see sja1105pqrs_dyn_l2_lookup_entry_packing) 63 * the .entry_packing is able to jump to the COMMAND portion, 64 * or vice-versa (sja1105pqrs_l2_lookup_cmd_packing). 65 * - .access: A bitmap of: 66 * OP_READ: Set if the hardware manual marks the ENTRY portion of the 67 * dynamic configuration table buffer as R (readable) after 68 * an SPI read command (the switch will populate the buffer). 69 * OP_WRITE: Set if the manual marks the ENTRY portion of the dynamic 70 * table buffer as W (writable) after an SPI write command 71 * (the switch will read the fields provided in the buffer). 72 * OP_DEL: Set if the manual says the VALIDENT bit is supported in the 73 * COMMAND portion of this dynamic config buffer (i.e. the 74 * specified entry can be invalidated through a SPI write 75 * command). 76 * OP_SEARCH: Set if the manual says that the index of an entry can 77 * be retrieved in the COMMAND portion of the buffer based 78 * on its ENTRY portion, as a result of a SPI write command. 79 * Only the TCAM-based FDB table on SJA1105 P/Q/R/S supports 80 * this. 81 * - .max_entry_count: The number of entries, counting from zero, that can be 82 * reconfigured through the dynamic interface. If a static 83 * table can be reconfigured at all dynamically, this 84 * number always matches the maximum number of supported 85 * static entries. 86 * - .packed_size: The length in bytes of the compound ENTRY + COMMAND BUFFER. 87 * Note that sometimes the compound buffer may contain holes in 88 * it (see sja1105_vlan_lookup_cmd_packing). The @packed_buf is 89 * contiguous however, so @packed_size includes any unused 90 * bytes. 91 * - .addr: The base SPI address at which the buffer must be written to the 92 * switch's memory. When looking at the hardware manual, this must 93 * always match the lowest documented address for the ENTRY, and not 94 * that of the COMMAND, since the other 32-bit words will follow along 95 * at the correct addresses. 96 */ 97 98 #define SJA1105_SIZE_DYN_CMD 4 99 100 #define SJA1105ET_SJA1105_SIZE_VL_LOOKUP_DYN_CMD \ 101 SJA1105_SIZE_DYN_CMD 102 103 #define SJA1105PQRS_SJA1105_SIZE_VL_LOOKUP_DYN_CMD \ 104 (SJA1105_SIZE_DYN_CMD + SJA1105_SIZE_VL_LOOKUP_ENTRY) 105 106 #define SJA1105ET_SIZE_MAC_CONFIG_DYN_ENTRY \ 107 SJA1105_SIZE_DYN_CMD 108 109 #define SJA1105ET_SIZE_L2_LOOKUP_DYN_CMD \ 110 (SJA1105_SIZE_DYN_CMD + SJA1105ET_SIZE_L2_LOOKUP_ENTRY) 111 112 #define SJA1105PQRS_SIZE_L2_LOOKUP_DYN_CMD \ 113 (SJA1105_SIZE_DYN_CMD + SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY) 114 115 #define SJA1105_SIZE_VLAN_LOOKUP_DYN_CMD \ 116 (SJA1105_SIZE_DYN_CMD + 4 + SJA1105_SIZE_VLAN_LOOKUP_ENTRY) 117 118 #define SJA1105_SIZE_L2_FORWARDING_DYN_CMD \ 119 (SJA1105_SIZE_DYN_CMD + SJA1105_SIZE_L2_FORWARDING_ENTRY) 120 121 #define SJA1105ET_SIZE_MAC_CONFIG_DYN_CMD \ 122 (SJA1105_SIZE_DYN_CMD + SJA1105ET_SIZE_MAC_CONFIG_DYN_ENTRY) 123 124 #define SJA1105PQRS_SIZE_MAC_CONFIG_DYN_CMD \ 125 (SJA1105_SIZE_DYN_CMD + SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY) 126 127 #define SJA1105ET_SIZE_L2_LOOKUP_PARAMS_DYN_CMD \ 128 SJA1105_SIZE_DYN_CMD 129 130 #define SJA1105ET_SIZE_GENERAL_PARAMS_DYN_CMD \ 131 SJA1105_SIZE_DYN_CMD 132 133 #define SJA1105PQRS_SIZE_AVB_PARAMS_DYN_CMD \ 134 (SJA1105_SIZE_DYN_CMD + SJA1105PQRS_SIZE_AVB_PARAMS_ENTRY) 135 136 #define SJA1105_SIZE_RETAGGING_DYN_CMD \ 137 (SJA1105_SIZE_DYN_CMD + SJA1105_SIZE_RETAGGING_ENTRY) 138 139 #define SJA1105_MAX_DYN_CMD_SIZE \ 140 SJA1105PQRS_SIZE_MAC_CONFIG_DYN_CMD 141 142 struct sja1105_dyn_cmd { 143 bool search; 144 u64 valid; 145 u64 rdwrset; 146 u64 errors; 147 u64 valident; 148 u64 index; 149 }; 150 151 enum sja1105_hostcmd { 152 SJA1105_HOSTCMD_SEARCH = 1, 153 SJA1105_HOSTCMD_READ = 2, 154 SJA1105_HOSTCMD_WRITE = 3, 155 SJA1105_HOSTCMD_INVALIDATE = 4, 156 }; 157 158 static void 159 sja1105_vl_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 160 enum packing_op op) 161 { 162 const int size = SJA1105_SIZE_DYN_CMD; 163 164 sja1105_packing(buf, &cmd->valid, 31, 31, size, op); 165 sja1105_packing(buf, &cmd->errors, 30, 30, size, op); 166 sja1105_packing(buf, &cmd->rdwrset, 29, 29, size, op); 167 sja1105_packing(buf, &cmd->index, 9, 0, size, op); 168 } 169 170 static size_t sja1105et_vl_lookup_entry_packing(void *buf, void *entry_ptr, 171 enum packing_op op) 172 { 173 struct sja1105_vl_lookup_entry *entry = entry_ptr; 174 const int size = SJA1105ET_SJA1105_SIZE_VL_LOOKUP_DYN_CMD; 175 176 sja1105_packing(buf, &entry->egrmirr, 21, 17, size, op); 177 sja1105_packing(buf, &entry->ingrmirr, 16, 16, size, op); 178 return size; 179 } 180 181 static void 182 sja1105pqrs_l2_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 183 enum packing_op op) 184 { 185 u8 *p = buf + SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY; 186 const int size = SJA1105_SIZE_DYN_CMD; 187 u64 hostcmd; 188 189 sja1105_packing(p, &cmd->valid, 31, 31, size, op); 190 sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op); 191 sja1105_packing(p, &cmd->errors, 29, 29, size, op); 192 sja1105_packing(p, &cmd->valident, 27, 27, size, op); 193 194 /* VALIDENT is supposed to indicate "keep or not", but in SJA1105 E/T, 195 * using it to delete a management route was unsupported. UM10944 196 * said about it: 197 * 198 * In case of a write access with the MGMTROUTE flag set, 199 * the flag will be ignored. It will always be found cleared 200 * for read accesses with the MGMTROUTE flag set. 201 * 202 * SJA1105 P/Q/R/S keeps the same behavior w.r.t. VALIDENT, but there 203 * is now another flag called HOSTCMD which does more stuff (quoting 204 * from UM11040): 205 * 206 * A write request is accepted only when HOSTCMD is set to write host 207 * or invalid. A read request is accepted only when HOSTCMD is set to 208 * search host or read host. 209 * 210 * So it is possible to translate a RDWRSET/VALIDENT combination into 211 * HOSTCMD so that we keep the dynamic command API in place, and 212 * at the same time achieve compatibility with the management route 213 * command structure. 214 */ 215 if (cmd->rdwrset == SPI_READ) { 216 if (cmd->search) 217 hostcmd = SJA1105_HOSTCMD_SEARCH; 218 else 219 hostcmd = SJA1105_HOSTCMD_READ; 220 } else { 221 /* SPI_WRITE */ 222 if (cmd->valident) 223 hostcmd = SJA1105_HOSTCMD_WRITE; 224 else 225 hostcmd = SJA1105_HOSTCMD_INVALIDATE; 226 } 227 sja1105_packing(p, &hostcmd, 25, 23, size, op); 228 229 /* Hack - The hardware takes the 'index' field within 230 * struct sja1105_l2_lookup_entry as the index on which this command 231 * will operate. However it will ignore everything else, so 'index' 232 * is logically part of command but physically part of entry. 233 * Populate the 'index' entry field from within the command callback, 234 * such that our API doesn't need to ask for a full-blown entry 235 * structure when e.g. a delete is requested. 236 */ 237 sja1105_packing(buf, &cmd->index, 15, 6, 238 SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY, op); 239 } 240 241 /* The switch is so retarded that it makes our command/entry abstraction 242 * crumble apart. 243 * 244 * On P/Q/R/S, the switch tries to say whether a FDB entry 245 * is statically programmed or dynamically learned via a flag called LOCKEDS. 246 * The hardware manual says about this fiels: 247 * 248 * On write will specify the format of ENTRY. 249 * On read the flag will be found cleared at times the VALID flag is found 250 * set. The flag will also be found cleared in response to a read having the 251 * MGMTROUTE flag set. In response to a read with the MGMTROUTE flag 252 * cleared, the flag be set if the most recent access operated on an entry 253 * that was either loaded by configuration or through dynamic reconfiguration 254 * (as opposed to automatically learned entries). 255 * 256 * The trouble with this flag is that it's part of the *command* to access the 257 * dynamic interface, and not part of the *entry* retrieved from it. 258 * Otherwise said, for a sja1105_dynamic_config_read, LOCKEDS is supposed to be 259 * an output from the switch into the command buffer, and for a 260 * sja1105_dynamic_config_write, the switch treats LOCKEDS as an input 261 * (hence we can write either static, or automatically learned entries, from 262 * the core). 263 * But the manual contradicts itself in the last phrase where it says that on 264 * read, LOCKEDS will be set to 1 for all FDB entries written through the 265 * dynamic interface (therefore, the value of LOCKEDS from the 266 * sja1105_dynamic_config_write is not really used for anything, it'll store a 267 * 1 anyway). 268 * This means you can't really write a FDB entry with LOCKEDS=0 (automatically 269 * learned) into the switch, which kind of makes sense. 270 * As for reading through the dynamic interface, it doesn't make too much sense 271 * to put LOCKEDS into the command, since the switch will inevitably have to 272 * ignore it (otherwise a command would be like "read the FDB entry 123, but 273 * only if it's dynamically learned" <- well how am I supposed to know?) and 274 * just use it as an output buffer for its findings. But guess what... that's 275 * what the entry buffer is for! 276 * Unfortunately, what really breaks this abstraction is the fact that it 277 * wasn't designed having the fact in mind that the switch can output 278 * entry-related data as writeback through the command buffer. 279 * However, whether a FDB entry is statically or dynamically learned *is* part 280 * of the entry and not the command data, no matter what the switch thinks. 281 * In order to do that, we'll need to wrap around the 282 * sja1105pqrs_l2_lookup_entry_packing from sja1105_static_config.c, and take 283 * a peek outside of the caller-supplied @buf (the entry buffer), to reach the 284 * command buffer. 285 */ 286 static size_t 287 sja1105pqrs_dyn_l2_lookup_entry_packing(void *buf, void *entry_ptr, 288 enum packing_op op) 289 { 290 struct sja1105_l2_lookup_entry *entry = entry_ptr; 291 u8 *cmd = buf + SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY; 292 const int size = SJA1105_SIZE_DYN_CMD; 293 294 sja1105_packing(cmd, &entry->lockeds, 28, 28, size, op); 295 296 return sja1105pqrs_l2_lookup_entry_packing(buf, entry_ptr, op); 297 } 298 299 static void 300 sja1105et_l2_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 301 enum packing_op op) 302 { 303 u8 *p = buf + SJA1105ET_SIZE_L2_LOOKUP_ENTRY; 304 const int size = SJA1105_SIZE_DYN_CMD; 305 306 sja1105_packing(p, &cmd->valid, 31, 31, size, op); 307 sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op); 308 sja1105_packing(p, &cmd->errors, 29, 29, size, op); 309 sja1105_packing(p, &cmd->valident, 27, 27, size, op); 310 /* Hack - see comments above. */ 311 sja1105_packing(buf, &cmd->index, 29, 20, 312 SJA1105ET_SIZE_L2_LOOKUP_ENTRY, op); 313 } 314 315 static size_t sja1105et_dyn_l2_lookup_entry_packing(void *buf, void *entry_ptr, 316 enum packing_op op) 317 { 318 struct sja1105_l2_lookup_entry *entry = entry_ptr; 319 u8 *cmd = buf + SJA1105ET_SIZE_L2_LOOKUP_ENTRY; 320 const int size = SJA1105_SIZE_DYN_CMD; 321 322 sja1105_packing(cmd, &entry->lockeds, 28, 28, size, op); 323 324 return sja1105et_l2_lookup_entry_packing(buf, entry_ptr, op); 325 } 326 327 static void 328 sja1105et_mgmt_route_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 329 enum packing_op op) 330 { 331 u8 *p = buf + SJA1105ET_SIZE_L2_LOOKUP_ENTRY; 332 u64 mgmtroute = 1; 333 334 sja1105et_l2_lookup_cmd_packing(buf, cmd, op); 335 if (op == PACK) 336 sja1105_pack(p, &mgmtroute, 26, 26, SJA1105_SIZE_DYN_CMD); 337 } 338 339 static size_t sja1105et_mgmt_route_entry_packing(void *buf, void *entry_ptr, 340 enum packing_op op) 341 { 342 struct sja1105_mgmt_entry *entry = entry_ptr; 343 const size_t size = SJA1105ET_SIZE_L2_LOOKUP_ENTRY; 344 345 /* UM10944: To specify if a PTP egress timestamp shall be captured on 346 * each port upon transmission of the frame, the LSB of VLANID in the 347 * ENTRY field provided by the host must be set. 348 * Bit 1 of VLANID then specifies the register where the timestamp for 349 * this port is stored in. 350 */ 351 sja1105_packing(buf, &entry->tsreg, 85, 85, size, op); 352 sja1105_packing(buf, &entry->takets, 84, 84, size, op); 353 sja1105_packing(buf, &entry->macaddr, 83, 36, size, op); 354 sja1105_packing(buf, &entry->destports, 35, 31, size, op); 355 sja1105_packing(buf, &entry->enfport, 30, 30, size, op); 356 return size; 357 } 358 359 static void 360 sja1105pqrs_mgmt_route_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 361 enum packing_op op) 362 { 363 u8 *p = buf + SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY; 364 u64 mgmtroute = 1; 365 366 sja1105pqrs_l2_lookup_cmd_packing(buf, cmd, op); 367 if (op == PACK) 368 sja1105_pack(p, &mgmtroute, 26, 26, SJA1105_SIZE_DYN_CMD); 369 } 370 371 static size_t sja1105pqrs_mgmt_route_entry_packing(void *buf, void *entry_ptr, 372 enum packing_op op) 373 { 374 const size_t size = SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY; 375 struct sja1105_mgmt_entry *entry = entry_ptr; 376 377 /* In P/Q/R/S, enfport got renamed to mgmtvalid, but its purpose 378 * is the same (driver uses it to confirm that frame was sent). 379 * So just keep the name from E/T. 380 */ 381 sja1105_packing(buf, &entry->tsreg, 71, 71, size, op); 382 sja1105_packing(buf, &entry->takets, 70, 70, size, op); 383 sja1105_packing(buf, &entry->macaddr, 69, 22, size, op); 384 sja1105_packing(buf, &entry->destports, 21, 17, size, op); 385 sja1105_packing(buf, &entry->enfport, 16, 16, size, op); 386 return size; 387 } 388 389 /* In E/T, entry is at addresses 0x27-0x28. There is a 4 byte gap at 0x29, 390 * and command is at 0x2a. Similarly in P/Q/R/S there is a 1 register gap 391 * between entry (0x2d, 0x2e) and command (0x30). 392 */ 393 static void 394 sja1105_vlan_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 395 enum packing_op op) 396 { 397 u8 *p = buf + SJA1105_SIZE_VLAN_LOOKUP_ENTRY + 4; 398 const int size = SJA1105_SIZE_DYN_CMD; 399 400 sja1105_packing(p, &cmd->valid, 31, 31, size, op); 401 sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op); 402 sja1105_packing(p, &cmd->valident, 27, 27, size, op); 403 /* Hack - see comments above, applied for 'vlanid' field of 404 * struct sja1105_vlan_lookup_entry. 405 */ 406 sja1105_packing(buf, &cmd->index, 38, 27, 407 SJA1105_SIZE_VLAN_LOOKUP_ENTRY, op); 408 } 409 410 static void 411 sja1105_l2_forwarding_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 412 enum packing_op op) 413 { 414 u8 *p = buf + SJA1105_SIZE_L2_FORWARDING_ENTRY; 415 const int size = SJA1105_SIZE_DYN_CMD; 416 417 sja1105_packing(p, &cmd->valid, 31, 31, size, op); 418 sja1105_packing(p, &cmd->errors, 30, 30, size, op); 419 sja1105_packing(p, &cmd->rdwrset, 29, 29, size, op); 420 sja1105_packing(p, &cmd->index, 4, 0, size, op); 421 } 422 423 static void 424 sja1105et_mac_config_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 425 enum packing_op op) 426 { 427 const int size = SJA1105_SIZE_DYN_CMD; 428 /* Yup, user manual definitions are reversed */ 429 u8 *reg1 = buf + 4; 430 431 sja1105_packing(reg1, &cmd->valid, 31, 31, size, op); 432 sja1105_packing(reg1, &cmd->index, 26, 24, size, op); 433 } 434 435 static size_t sja1105et_mac_config_entry_packing(void *buf, void *entry_ptr, 436 enum packing_op op) 437 { 438 const int size = SJA1105ET_SIZE_MAC_CONFIG_DYN_ENTRY; 439 struct sja1105_mac_config_entry *entry = entry_ptr; 440 /* Yup, user manual definitions are reversed */ 441 u8 *reg1 = buf + 4; 442 u8 *reg2 = buf; 443 444 sja1105_packing(reg1, &entry->speed, 30, 29, size, op); 445 sja1105_packing(reg1, &entry->drpdtag, 23, 23, size, op); 446 sja1105_packing(reg1, &entry->drpuntag, 22, 22, size, op); 447 sja1105_packing(reg1, &entry->retag, 21, 21, size, op); 448 sja1105_packing(reg1, &entry->dyn_learn, 20, 20, size, op); 449 sja1105_packing(reg1, &entry->egress, 19, 19, size, op); 450 sja1105_packing(reg1, &entry->ingress, 18, 18, size, op); 451 sja1105_packing(reg1, &entry->ing_mirr, 17, 17, size, op); 452 sja1105_packing(reg1, &entry->egr_mirr, 16, 16, size, op); 453 sja1105_packing(reg1, &entry->vlanprio, 14, 12, size, op); 454 sja1105_packing(reg1, &entry->vlanid, 11, 0, size, op); 455 sja1105_packing(reg2, &entry->tp_delin, 31, 16, size, op); 456 sja1105_packing(reg2, &entry->tp_delout, 15, 0, size, op); 457 /* MAC configuration table entries which can't be reconfigured: 458 * top, base, enabled, ifg, maxage, drpnona664 459 */ 460 /* Bogus return value, not used anywhere */ 461 return 0; 462 } 463 464 static void 465 sja1105pqrs_mac_config_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 466 enum packing_op op) 467 { 468 const int size = SJA1105ET_SIZE_MAC_CONFIG_DYN_ENTRY; 469 u8 *p = buf + SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY; 470 471 sja1105_packing(p, &cmd->valid, 31, 31, size, op); 472 sja1105_packing(p, &cmd->errors, 30, 30, size, op); 473 sja1105_packing(p, &cmd->rdwrset, 29, 29, size, op); 474 sja1105_packing(p, &cmd->index, 2, 0, size, op); 475 } 476 477 static void 478 sja1105et_l2_lookup_params_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 479 enum packing_op op) 480 { 481 sja1105_packing(buf, &cmd->valid, 31, 31, 482 SJA1105ET_SIZE_L2_LOOKUP_PARAMS_DYN_CMD, op); 483 } 484 485 static size_t 486 sja1105et_l2_lookup_params_entry_packing(void *buf, void *entry_ptr, 487 enum packing_op op) 488 { 489 struct sja1105_l2_lookup_params_entry *entry = entry_ptr; 490 491 sja1105_packing(buf, &entry->poly, 7, 0, 492 SJA1105ET_SIZE_L2_LOOKUP_PARAMS_DYN_CMD, op); 493 /* Bogus return value, not used anywhere */ 494 return 0; 495 } 496 497 static void 498 sja1105et_general_params_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 499 enum packing_op op) 500 { 501 const int size = SJA1105ET_SIZE_GENERAL_PARAMS_DYN_CMD; 502 503 sja1105_packing(buf, &cmd->valid, 31, 31, size, op); 504 sja1105_packing(buf, &cmd->errors, 30, 30, size, op); 505 } 506 507 static size_t 508 sja1105et_general_params_entry_packing(void *buf, void *entry_ptr, 509 enum packing_op op) 510 { 511 struct sja1105_general_params_entry *entry = entry_ptr; 512 const int size = SJA1105ET_SIZE_GENERAL_PARAMS_DYN_CMD; 513 514 sja1105_packing(buf, &entry->mirr_port, 2, 0, size, op); 515 /* Bogus return value, not used anywhere */ 516 return 0; 517 } 518 519 static void 520 sja1105pqrs_avb_params_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 521 enum packing_op op) 522 { 523 u8 *p = buf + SJA1105PQRS_SIZE_AVB_PARAMS_ENTRY; 524 const int size = SJA1105_SIZE_DYN_CMD; 525 526 sja1105_packing(p, &cmd->valid, 31, 31, size, op); 527 sja1105_packing(p, &cmd->errors, 30, 30, size, op); 528 sja1105_packing(p, &cmd->rdwrset, 29, 29, size, op); 529 } 530 531 static void 532 sja1105_retagging_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 533 enum packing_op op) 534 { 535 u8 *p = buf + SJA1105_SIZE_RETAGGING_ENTRY; 536 const int size = SJA1105_SIZE_DYN_CMD; 537 538 sja1105_packing(p, &cmd->valid, 31, 31, size, op); 539 sja1105_packing(p, &cmd->errors, 30, 30, size, op); 540 sja1105_packing(p, &cmd->valident, 29, 29, size, op); 541 sja1105_packing(p, &cmd->rdwrset, 28, 28, size, op); 542 sja1105_packing(p, &cmd->index, 5, 0, size, op); 543 } 544 545 #define OP_READ BIT(0) 546 #define OP_WRITE BIT(1) 547 #define OP_DEL BIT(2) 548 #define OP_SEARCH BIT(3) 549 550 /* SJA1105E/T: First generation */ 551 struct sja1105_dynamic_table_ops sja1105et_dyn_ops[BLK_IDX_MAX_DYN] = { 552 [BLK_IDX_SCHEDULE] = {0}, 553 [BLK_IDX_SCHEDULE_ENTRY_POINTS] = {0}, 554 [BLK_IDX_VL_LOOKUP] = { 555 .entry_packing = sja1105et_vl_lookup_entry_packing, 556 .cmd_packing = sja1105_vl_lookup_cmd_packing, 557 .access = OP_WRITE, 558 .max_entry_count = SJA1105_MAX_VL_LOOKUP_COUNT, 559 .packed_size = SJA1105ET_SJA1105_SIZE_VL_LOOKUP_DYN_CMD, 560 .addr = 0x35, 561 }, 562 [BLK_IDX_VL_POLICING] = {0}, 563 [BLK_IDX_VL_FORWARDING] = {0}, 564 [BLK_IDX_L2_LOOKUP] = { 565 .entry_packing = sja1105et_dyn_l2_lookup_entry_packing, 566 .cmd_packing = sja1105et_l2_lookup_cmd_packing, 567 .access = (OP_READ | OP_WRITE | OP_DEL), 568 .max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT, 569 .packed_size = SJA1105ET_SIZE_L2_LOOKUP_DYN_CMD, 570 .addr = 0x20, 571 }, 572 [BLK_IDX_MGMT_ROUTE] = { 573 .entry_packing = sja1105et_mgmt_route_entry_packing, 574 .cmd_packing = sja1105et_mgmt_route_cmd_packing, 575 .access = (OP_READ | OP_WRITE), 576 .max_entry_count = SJA1105_NUM_PORTS, 577 .packed_size = SJA1105ET_SIZE_L2_LOOKUP_DYN_CMD, 578 .addr = 0x20, 579 }, 580 [BLK_IDX_L2_POLICING] = {0}, 581 [BLK_IDX_VLAN_LOOKUP] = { 582 .entry_packing = sja1105_vlan_lookup_entry_packing, 583 .cmd_packing = sja1105_vlan_lookup_cmd_packing, 584 .access = (OP_WRITE | OP_DEL), 585 .max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT, 586 .packed_size = SJA1105_SIZE_VLAN_LOOKUP_DYN_CMD, 587 .addr = 0x27, 588 }, 589 [BLK_IDX_L2_FORWARDING] = { 590 .entry_packing = sja1105_l2_forwarding_entry_packing, 591 .cmd_packing = sja1105_l2_forwarding_cmd_packing, 592 .max_entry_count = SJA1105_MAX_L2_FORWARDING_COUNT, 593 .access = OP_WRITE, 594 .packed_size = SJA1105_SIZE_L2_FORWARDING_DYN_CMD, 595 .addr = 0x24, 596 }, 597 [BLK_IDX_MAC_CONFIG] = { 598 .entry_packing = sja1105et_mac_config_entry_packing, 599 .cmd_packing = sja1105et_mac_config_cmd_packing, 600 .max_entry_count = SJA1105_MAX_MAC_CONFIG_COUNT, 601 .access = OP_WRITE, 602 .packed_size = SJA1105ET_SIZE_MAC_CONFIG_DYN_CMD, 603 .addr = 0x36, 604 }, 605 [BLK_IDX_SCHEDULE_PARAMS] = {0}, 606 [BLK_IDX_SCHEDULE_ENTRY_POINTS_PARAMS] = {0}, 607 [BLK_IDX_VL_FORWARDING_PARAMS] = {0}, 608 [BLK_IDX_L2_LOOKUP_PARAMS] = { 609 .entry_packing = sja1105et_l2_lookup_params_entry_packing, 610 .cmd_packing = sja1105et_l2_lookup_params_cmd_packing, 611 .max_entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT, 612 .access = OP_WRITE, 613 .packed_size = SJA1105ET_SIZE_L2_LOOKUP_PARAMS_DYN_CMD, 614 .addr = 0x38, 615 }, 616 [BLK_IDX_L2_FORWARDING_PARAMS] = {0}, 617 [BLK_IDX_AVB_PARAMS] = {0}, 618 [BLK_IDX_GENERAL_PARAMS] = { 619 .entry_packing = sja1105et_general_params_entry_packing, 620 .cmd_packing = sja1105et_general_params_cmd_packing, 621 .max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT, 622 .access = OP_WRITE, 623 .packed_size = SJA1105ET_SIZE_GENERAL_PARAMS_DYN_CMD, 624 .addr = 0x34, 625 }, 626 [BLK_IDX_RETAGGING] = { 627 .entry_packing = sja1105_retagging_entry_packing, 628 .cmd_packing = sja1105_retagging_cmd_packing, 629 .max_entry_count = SJA1105_MAX_RETAGGING_COUNT, 630 .access = (OP_WRITE | OP_DEL), 631 .packed_size = SJA1105_SIZE_RETAGGING_DYN_CMD, 632 .addr = 0x31, 633 }, 634 [BLK_IDX_XMII_PARAMS] = {0}, 635 }; 636 637 /* SJA1105P/Q/R/S: Second generation */ 638 struct sja1105_dynamic_table_ops sja1105pqrs_dyn_ops[BLK_IDX_MAX_DYN] = { 639 [BLK_IDX_SCHEDULE] = {0}, 640 [BLK_IDX_SCHEDULE_ENTRY_POINTS] = {0}, 641 [BLK_IDX_VL_LOOKUP] = { 642 .entry_packing = sja1105_vl_lookup_entry_packing, 643 .cmd_packing = sja1105_vl_lookup_cmd_packing, 644 .access = (OP_READ | OP_WRITE), 645 .max_entry_count = SJA1105_MAX_VL_LOOKUP_COUNT, 646 .packed_size = SJA1105PQRS_SJA1105_SIZE_VL_LOOKUP_DYN_CMD, 647 .addr = 0x47, 648 }, 649 [BLK_IDX_VL_POLICING] = {0}, 650 [BLK_IDX_VL_FORWARDING] = {0}, 651 [BLK_IDX_L2_LOOKUP] = { 652 .entry_packing = sja1105pqrs_dyn_l2_lookup_entry_packing, 653 .cmd_packing = sja1105pqrs_l2_lookup_cmd_packing, 654 .access = (OP_READ | OP_WRITE | OP_DEL | OP_SEARCH), 655 .max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT, 656 .packed_size = SJA1105PQRS_SIZE_L2_LOOKUP_DYN_CMD, 657 .addr = 0x24, 658 }, 659 [BLK_IDX_MGMT_ROUTE] = { 660 .entry_packing = sja1105pqrs_mgmt_route_entry_packing, 661 .cmd_packing = sja1105pqrs_mgmt_route_cmd_packing, 662 .access = (OP_READ | OP_WRITE | OP_DEL | OP_SEARCH), 663 .max_entry_count = SJA1105_NUM_PORTS, 664 .packed_size = SJA1105PQRS_SIZE_L2_LOOKUP_DYN_CMD, 665 .addr = 0x24, 666 }, 667 [BLK_IDX_L2_POLICING] = {0}, 668 [BLK_IDX_VLAN_LOOKUP] = { 669 .entry_packing = sja1105_vlan_lookup_entry_packing, 670 .cmd_packing = sja1105_vlan_lookup_cmd_packing, 671 .access = (OP_READ | OP_WRITE | OP_DEL), 672 .max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT, 673 .packed_size = SJA1105_SIZE_VLAN_LOOKUP_DYN_CMD, 674 .addr = 0x2D, 675 }, 676 [BLK_IDX_L2_FORWARDING] = { 677 .entry_packing = sja1105_l2_forwarding_entry_packing, 678 .cmd_packing = sja1105_l2_forwarding_cmd_packing, 679 .max_entry_count = SJA1105_MAX_L2_FORWARDING_COUNT, 680 .access = OP_WRITE, 681 .packed_size = SJA1105_SIZE_L2_FORWARDING_DYN_CMD, 682 .addr = 0x2A, 683 }, 684 [BLK_IDX_MAC_CONFIG] = { 685 .entry_packing = sja1105pqrs_mac_config_entry_packing, 686 .cmd_packing = sja1105pqrs_mac_config_cmd_packing, 687 .max_entry_count = SJA1105_MAX_MAC_CONFIG_COUNT, 688 .access = (OP_READ | OP_WRITE), 689 .packed_size = SJA1105PQRS_SIZE_MAC_CONFIG_DYN_CMD, 690 .addr = 0x4B, 691 }, 692 [BLK_IDX_SCHEDULE_PARAMS] = {0}, 693 [BLK_IDX_SCHEDULE_ENTRY_POINTS_PARAMS] = {0}, 694 [BLK_IDX_VL_FORWARDING_PARAMS] = {0}, 695 [BLK_IDX_L2_LOOKUP_PARAMS] = { 696 .entry_packing = sja1105et_l2_lookup_params_entry_packing, 697 .cmd_packing = sja1105et_l2_lookup_params_cmd_packing, 698 .max_entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT, 699 .access = (OP_READ | OP_WRITE), 700 .packed_size = SJA1105ET_SIZE_L2_LOOKUP_PARAMS_DYN_CMD, 701 .addr = 0x38, 702 }, 703 [BLK_IDX_L2_FORWARDING_PARAMS] = {0}, 704 [BLK_IDX_AVB_PARAMS] = { 705 .entry_packing = sja1105pqrs_avb_params_entry_packing, 706 .cmd_packing = sja1105pqrs_avb_params_cmd_packing, 707 .max_entry_count = SJA1105_MAX_AVB_PARAMS_COUNT, 708 .access = (OP_READ | OP_WRITE), 709 .packed_size = SJA1105PQRS_SIZE_AVB_PARAMS_DYN_CMD, 710 .addr = 0x8003, 711 }, 712 [BLK_IDX_GENERAL_PARAMS] = { 713 .entry_packing = sja1105et_general_params_entry_packing, 714 .cmd_packing = sja1105et_general_params_cmd_packing, 715 .max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT, 716 .access = OP_WRITE, 717 .packed_size = SJA1105ET_SIZE_GENERAL_PARAMS_DYN_CMD, 718 .addr = 0x34, 719 }, 720 [BLK_IDX_RETAGGING] = { 721 .entry_packing = sja1105_retagging_entry_packing, 722 .cmd_packing = sja1105_retagging_cmd_packing, 723 .max_entry_count = SJA1105_MAX_RETAGGING_COUNT, 724 .access = (OP_READ | OP_WRITE | OP_DEL), 725 .packed_size = SJA1105_SIZE_RETAGGING_DYN_CMD, 726 .addr = 0x38, 727 }, 728 [BLK_IDX_XMII_PARAMS] = {0}, 729 }; 730 731 /* Provides read access to the settings through the dynamic interface 732 * of the switch. 733 * @blk_idx is used as key to select from the sja1105_dynamic_table_ops. 734 * The selection is limited by the hardware in respect to which 735 * configuration blocks can be read through the dynamic interface. 736 * @index is used to retrieve a particular table entry. If negative, 737 * (and if the @blk_idx supports the searching operation) a search 738 * is performed by the @entry parameter. 739 * @entry Type-casted to an unpacked structure that holds a table entry 740 * of the type specified in @blk_idx. 741 * Usually an output argument. If @index is negative, then this 742 * argument is used as input/output: it should be pre-populated 743 * with the element to search for. Entries which support the 744 * search operation will have an "index" field (not the @index 745 * argument to this function) and that is where the found index 746 * will be returned (or left unmodified - thus negative - if not 747 * found). 748 */ 749 int sja1105_dynamic_config_read(struct sja1105_private *priv, 750 enum sja1105_blk_idx blk_idx, 751 int index, void *entry) 752 { 753 const struct sja1105_dynamic_table_ops *ops; 754 struct sja1105_dyn_cmd cmd = {0}; 755 /* SPI payload buffer */ 756 u8 packed_buf[SJA1105_MAX_DYN_CMD_SIZE] = {0}; 757 int retries = 3; 758 int rc; 759 760 if (blk_idx >= BLK_IDX_MAX_DYN) 761 return -ERANGE; 762 763 ops = &priv->info->dyn_ops[blk_idx]; 764 765 if (index >= 0 && index >= ops->max_entry_count) 766 return -ERANGE; 767 if (index < 0 && !(ops->access & OP_SEARCH)) 768 return -EOPNOTSUPP; 769 if (!(ops->access & OP_READ)) 770 return -EOPNOTSUPP; 771 if (ops->packed_size > SJA1105_MAX_DYN_CMD_SIZE) 772 return -ERANGE; 773 if (!ops->cmd_packing) 774 return -EOPNOTSUPP; 775 if (!ops->entry_packing) 776 return -EOPNOTSUPP; 777 778 cmd.valid = true; /* Trigger action on table entry */ 779 cmd.rdwrset = SPI_READ; /* Action is read */ 780 if (index < 0) { 781 /* Avoid copying a signed negative number to an u64 */ 782 cmd.index = 0; 783 cmd.search = true; 784 } else { 785 cmd.index = index; 786 cmd.search = false; 787 } 788 cmd.valident = true; 789 ops->cmd_packing(packed_buf, &cmd, PACK); 790 791 if (cmd.search) 792 ops->entry_packing(packed_buf, entry, PACK); 793 794 /* Send SPI write operation: read config table entry */ 795 rc = sja1105_xfer_buf(priv, SPI_WRITE, ops->addr, packed_buf, 796 ops->packed_size); 797 if (rc < 0) 798 return rc; 799 800 /* Loop until we have confirmation that hardware has finished 801 * processing the command and has cleared the VALID field 802 */ 803 do { 804 memset(packed_buf, 0, ops->packed_size); 805 806 /* Retrieve the read operation's result */ 807 rc = sja1105_xfer_buf(priv, SPI_READ, ops->addr, packed_buf, 808 ops->packed_size); 809 if (rc < 0) 810 return rc; 811 812 cmd = (struct sja1105_dyn_cmd) {0}; 813 ops->cmd_packing(packed_buf, &cmd, UNPACK); 814 /* UM10944: [valident] will always be found cleared 815 * during a read access with MGMTROUTE set. 816 * So don't error out in that case. 817 */ 818 if (!cmd.valident && blk_idx != BLK_IDX_MGMT_ROUTE) 819 return -ENOENT; 820 cpu_relax(); 821 } while (cmd.valid && --retries); 822 823 if (cmd.valid) 824 return -ETIMEDOUT; 825 826 /* Don't dereference possibly NULL pointer - maybe caller 827 * only wanted to see whether the entry existed or not. 828 */ 829 if (entry) 830 ops->entry_packing(packed_buf, entry, UNPACK); 831 return 0; 832 } 833 834 int sja1105_dynamic_config_write(struct sja1105_private *priv, 835 enum sja1105_blk_idx blk_idx, 836 int index, void *entry, bool keep) 837 { 838 const struct sja1105_dynamic_table_ops *ops; 839 struct sja1105_dyn_cmd cmd = {0}; 840 /* SPI payload buffer */ 841 u8 packed_buf[SJA1105_MAX_DYN_CMD_SIZE] = {0}; 842 int rc; 843 844 if (blk_idx >= BLK_IDX_MAX_DYN) 845 return -ERANGE; 846 847 ops = &priv->info->dyn_ops[blk_idx]; 848 849 if (index >= ops->max_entry_count) 850 return -ERANGE; 851 if (index < 0) 852 return -ERANGE; 853 if (!(ops->access & OP_WRITE)) 854 return -EOPNOTSUPP; 855 if (!keep && !(ops->access & OP_DEL)) 856 return -EOPNOTSUPP; 857 if (ops->packed_size > SJA1105_MAX_DYN_CMD_SIZE) 858 return -ERANGE; 859 860 cmd.valident = keep; /* If false, deletes entry */ 861 cmd.valid = true; /* Trigger action on table entry */ 862 cmd.rdwrset = SPI_WRITE; /* Action is write */ 863 cmd.index = index; 864 865 if (!ops->cmd_packing) 866 return -EOPNOTSUPP; 867 ops->cmd_packing(packed_buf, &cmd, PACK); 868 869 if (!ops->entry_packing) 870 return -EOPNOTSUPP; 871 /* Don't dereference potentially NULL pointer if just 872 * deleting a table entry is what was requested. For cases 873 * where 'index' field is physically part of entry structure, 874 * and needed here, we deal with that in the cmd_packing callback. 875 */ 876 if (keep) 877 ops->entry_packing(packed_buf, entry, PACK); 878 879 /* Send SPI write operation: read config table entry */ 880 rc = sja1105_xfer_buf(priv, SPI_WRITE, ops->addr, packed_buf, 881 ops->packed_size); 882 if (rc < 0) 883 return rc; 884 885 cmd = (struct sja1105_dyn_cmd) {0}; 886 ops->cmd_packing(packed_buf, &cmd, UNPACK); 887 if (cmd.errors) 888 return -EINVAL; 889 890 return 0; 891 } 892 893 static u8 sja1105_crc8_add(u8 crc, u8 byte, u8 poly) 894 { 895 int i; 896 897 for (i = 0; i < 8; i++) { 898 if ((crc ^ byte) & (1 << 7)) { 899 crc <<= 1; 900 crc ^= poly; 901 } else { 902 crc <<= 1; 903 } 904 byte <<= 1; 905 } 906 return crc; 907 } 908 909 /* CRC8 algorithm with non-reversed input, non-reversed output, 910 * no input xor and no output xor. Code customized for receiving 911 * the SJA1105 E/T FDB keys (vlanid, macaddr) as input. CRC polynomial 912 * is also received as argument in the Koopman notation that the switch 913 * hardware stores it in. 914 */ 915 u8 sja1105et_fdb_hash(struct sja1105_private *priv, const u8 *addr, u16 vid) 916 { 917 struct sja1105_l2_lookup_params_entry *l2_lookup_params = 918 priv->static_config.tables[BLK_IDX_L2_LOOKUP_PARAMS].entries; 919 u64 poly_koopman = l2_lookup_params->poly; 920 /* Convert polynomial from Koopman to 'normal' notation */ 921 u8 poly = (u8)(1 + (poly_koopman << 1)); 922 u64 vlanid = l2_lookup_params->shared_learn ? 0 : vid; 923 u64 input = (vlanid << 48) | ether_addr_to_u64(addr); 924 u8 crc = 0; /* seed */ 925 int i; 926 927 /* Mask the eight bytes starting from MSB one at a time */ 928 for (i = 56; i >= 0; i -= 8) { 929 u8 byte = (input & (0xffull << i)) >> i; 930 931 crc = sja1105_crc8_add(crc, byte, poly); 932 } 933 return crc; 934 } 935