162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com> 362306a36Sopenharmony_ci */ 462306a36Sopenharmony_ci#include "sja1105.h" 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci/* In the dynamic configuration interface, the switch exposes a register-like 762306a36Sopenharmony_ci * view of some of the static configuration tables. 862306a36Sopenharmony_ci * Many times the field organization of the dynamic tables is abbreviated (not 962306a36Sopenharmony_ci * all fields are dynamically reconfigurable) and different from the static 1062306a36Sopenharmony_ci * ones, but the key reason for having it is that we can spare a switch reset 1162306a36Sopenharmony_ci * for settings that can be changed dynamically. 1262306a36Sopenharmony_ci * 1362306a36Sopenharmony_ci * This file creates a per-switch-family abstraction called 1462306a36Sopenharmony_ci * struct sja1105_dynamic_table_ops and two operations that work with it: 1562306a36Sopenharmony_ci * - sja1105_dynamic_config_write 1662306a36Sopenharmony_ci * - sja1105_dynamic_config_read 1762306a36Sopenharmony_ci * 1862306a36Sopenharmony_ci * Compared to the struct sja1105_table_ops from sja1105_static_config.c, 1962306a36Sopenharmony_ci * the dynamic accessors work with a compound buffer: 2062306a36Sopenharmony_ci * 2162306a36Sopenharmony_ci * packed_buf 2262306a36Sopenharmony_ci * 2362306a36Sopenharmony_ci * | 2462306a36Sopenharmony_ci * V 2562306a36Sopenharmony_ci * +-----------------------------------------+------------------+ 2662306a36Sopenharmony_ci * | ENTRY BUFFER | COMMAND BUFFER | 2762306a36Sopenharmony_ci * +-----------------------------------------+------------------+ 2862306a36Sopenharmony_ci * 2962306a36Sopenharmony_ci * <----------------------- packed_size ------------------------> 3062306a36Sopenharmony_ci * 3162306a36Sopenharmony_ci * The ENTRY BUFFER may or may not have the same layout, or size, as its static 3262306a36Sopenharmony_ci * configuration table entry counterpart. When it does, the same packing 3362306a36Sopenharmony_ci * function is reused (bar exceptional cases - see 3462306a36Sopenharmony_ci * sja1105pqrs_dyn_l2_lookup_entry_packing). 3562306a36Sopenharmony_ci * 3662306a36Sopenharmony_ci * The reason for the COMMAND BUFFER being at the end is to be able to send 3762306a36Sopenharmony_ci * a dynamic write command through a single SPI burst. By the time the switch 3862306a36Sopenharmony_ci * reacts to the command, the ENTRY BUFFER is already populated with the data 3962306a36Sopenharmony_ci * sent by the core. 4062306a36Sopenharmony_ci * 4162306a36Sopenharmony_ci * The COMMAND BUFFER is always SJA1105_SIZE_DYN_CMD bytes (one 32-bit word) in 4262306a36Sopenharmony_ci * size. 4362306a36Sopenharmony_ci * 4462306a36Sopenharmony_ci * Sometimes the ENTRY BUFFER does not really exist (when the number of fields 4562306a36Sopenharmony_ci * that can be reconfigured is small), then the switch repurposes some of the 4662306a36Sopenharmony_ci * unused 32 bits of the COMMAND BUFFER to hold ENTRY data. 4762306a36Sopenharmony_ci * 4862306a36Sopenharmony_ci * The key members of struct sja1105_dynamic_table_ops are: 4962306a36Sopenharmony_ci * - .entry_packing: A function that deals with packing an ENTRY structure 5062306a36Sopenharmony_ci * into an SPI buffer, or retrieving an ENTRY structure 5162306a36Sopenharmony_ci * from one. 5262306a36Sopenharmony_ci * The @packed_buf pointer it's given does always point to 5362306a36Sopenharmony_ci * the ENTRY portion of the buffer. 5462306a36Sopenharmony_ci * - .cmd_packing: A function that deals with packing/unpacking the COMMAND 5562306a36Sopenharmony_ci * structure to/from the SPI buffer. 5662306a36Sopenharmony_ci * It is given the same @packed_buf pointer as .entry_packing, 5762306a36Sopenharmony_ci * so most of the time, the @packed_buf points *behind* the 5862306a36Sopenharmony_ci * COMMAND offset inside the buffer. 5962306a36Sopenharmony_ci * To access the COMMAND portion of the buffer, the function 6062306a36Sopenharmony_ci * knows its correct offset. 6162306a36Sopenharmony_ci * Giving both functions the same pointer is handy because in 6262306a36Sopenharmony_ci * extreme cases (see sja1105pqrs_dyn_l2_lookup_entry_packing) 6362306a36Sopenharmony_ci * the .entry_packing is able to jump to the COMMAND portion, 6462306a36Sopenharmony_ci * or vice-versa (sja1105pqrs_l2_lookup_cmd_packing). 6562306a36Sopenharmony_ci * - .access: A bitmap of: 6662306a36Sopenharmony_ci * OP_READ: Set if the hardware manual marks the ENTRY portion of the 6762306a36Sopenharmony_ci * dynamic configuration table buffer as R (readable) after 6862306a36Sopenharmony_ci * an SPI read command (the switch will populate the buffer). 6962306a36Sopenharmony_ci * OP_WRITE: Set if the manual marks the ENTRY portion of the dynamic 7062306a36Sopenharmony_ci * table buffer as W (writable) after an SPI write command 7162306a36Sopenharmony_ci * (the switch will read the fields provided in the buffer). 7262306a36Sopenharmony_ci * OP_DEL: Set if the manual says the VALIDENT bit is supported in the 7362306a36Sopenharmony_ci * COMMAND portion of this dynamic config buffer (i.e. the 7462306a36Sopenharmony_ci * specified entry can be invalidated through a SPI write 7562306a36Sopenharmony_ci * command). 7662306a36Sopenharmony_ci * OP_SEARCH: Set if the manual says that the index of an entry can 7762306a36Sopenharmony_ci * be retrieved in the COMMAND portion of the buffer based 7862306a36Sopenharmony_ci * on its ENTRY portion, as a result of a SPI write command. 7962306a36Sopenharmony_ci * Only the TCAM-based FDB table on SJA1105 P/Q/R/S supports 8062306a36Sopenharmony_ci * this. 8162306a36Sopenharmony_ci * OP_VALID_ANYWAY: Reading some tables through the dynamic config 8262306a36Sopenharmony_ci * interface is possible even if the VALIDENT bit is not 8362306a36Sopenharmony_ci * set in the writeback. So don't error out in that case. 8462306a36Sopenharmony_ci * - .max_entry_count: The number of entries, counting from zero, that can be 8562306a36Sopenharmony_ci * reconfigured through the dynamic interface. If a static 8662306a36Sopenharmony_ci * table can be reconfigured at all dynamically, this 8762306a36Sopenharmony_ci * number always matches the maximum number of supported 8862306a36Sopenharmony_ci * static entries. 8962306a36Sopenharmony_ci * - .packed_size: The length in bytes of the compound ENTRY + COMMAND BUFFER. 9062306a36Sopenharmony_ci * Note that sometimes the compound buffer may contain holes in 9162306a36Sopenharmony_ci * it (see sja1105_vlan_lookup_cmd_packing). The @packed_buf is 9262306a36Sopenharmony_ci * contiguous however, so @packed_size includes any unused 9362306a36Sopenharmony_ci * bytes. 9462306a36Sopenharmony_ci * - .addr: The base SPI address at which the buffer must be written to the 9562306a36Sopenharmony_ci * switch's memory. When looking at the hardware manual, this must 9662306a36Sopenharmony_ci * always match the lowest documented address for the ENTRY, and not 9762306a36Sopenharmony_ci * that of the COMMAND, since the other 32-bit words will follow along 9862306a36Sopenharmony_ci * at the correct addresses. 9962306a36Sopenharmony_ci */ 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci#define SJA1105_SIZE_DYN_CMD 4 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci#define SJA1105ET_SIZE_VL_LOOKUP_DYN_CMD \ 10462306a36Sopenharmony_ci SJA1105_SIZE_DYN_CMD 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci#define SJA1105PQRS_SIZE_VL_LOOKUP_DYN_CMD \ 10762306a36Sopenharmony_ci (SJA1105_SIZE_DYN_CMD + SJA1105_SIZE_VL_LOOKUP_ENTRY) 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci#define SJA1110_SIZE_VL_POLICING_DYN_CMD \ 11062306a36Sopenharmony_ci (SJA1105_SIZE_DYN_CMD + SJA1105_SIZE_VL_POLICING_ENTRY) 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci#define SJA1105ET_SIZE_MAC_CONFIG_DYN_ENTRY \ 11362306a36Sopenharmony_ci SJA1105_SIZE_DYN_CMD 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci#define SJA1105ET_SIZE_L2_LOOKUP_DYN_CMD \ 11662306a36Sopenharmony_ci (SJA1105_SIZE_DYN_CMD + SJA1105ET_SIZE_L2_LOOKUP_ENTRY) 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci#define SJA1105PQRS_SIZE_L2_LOOKUP_DYN_CMD \ 11962306a36Sopenharmony_ci (SJA1105_SIZE_DYN_CMD + SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY) 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci#define SJA1110_SIZE_L2_LOOKUP_DYN_CMD \ 12262306a36Sopenharmony_ci (SJA1105_SIZE_DYN_CMD + SJA1110_SIZE_L2_LOOKUP_ENTRY) 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci#define SJA1105_SIZE_VLAN_LOOKUP_DYN_CMD \ 12562306a36Sopenharmony_ci (SJA1105_SIZE_DYN_CMD + 4 + SJA1105_SIZE_VLAN_LOOKUP_ENTRY) 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci#define SJA1110_SIZE_VLAN_LOOKUP_DYN_CMD \ 12862306a36Sopenharmony_ci (SJA1105_SIZE_DYN_CMD + SJA1110_SIZE_VLAN_LOOKUP_ENTRY) 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci#define SJA1105_SIZE_L2_FORWARDING_DYN_CMD \ 13162306a36Sopenharmony_ci (SJA1105_SIZE_DYN_CMD + SJA1105_SIZE_L2_FORWARDING_ENTRY) 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci#define SJA1105ET_SIZE_MAC_CONFIG_DYN_CMD \ 13462306a36Sopenharmony_ci (SJA1105_SIZE_DYN_CMD + SJA1105ET_SIZE_MAC_CONFIG_DYN_ENTRY) 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci#define SJA1105PQRS_SIZE_MAC_CONFIG_DYN_CMD \ 13762306a36Sopenharmony_ci (SJA1105_SIZE_DYN_CMD + SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY) 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci#define SJA1105ET_SIZE_L2_LOOKUP_PARAMS_DYN_CMD \ 14062306a36Sopenharmony_ci SJA1105_SIZE_DYN_CMD 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci#define SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_DYN_CMD \ 14362306a36Sopenharmony_ci (SJA1105_SIZE_DYN_CMD + SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_ENTRY) 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci#define SJA1110_SIZE_L2_LOOKUP_PARAMS_DYN_CMD \ 14662306a36Sopenharmony_ci (SJA1105_SIZE_DYN_CMD + SJA1110_SIZE_L2_LOOKUP_PARAMS_ENTRY) 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci#define SJA1105ET_SIZE_GENERAL_PARAMS_DYN_CMD \ 14962306a36Sopenharmony_ci SJA1105_SIZE_DYN_CMD 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci#define SJA1105PQRS_SIZE_GENERAL_PARAMS_DYN_CMD \ 15262306a36Sopenharmony_ci (SJA1105_SIZE_DYN_CMD + SJA1105PQRS_SIZE_GENERAL_PARAMS_ENTRY) 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci#define SJA1110_SIZE_GENERAL_PARAMS_DYN_CMD \ 15562306a36Sopenharmony_ci (SJA1105_SIZE_DYN_CMD + SJA1110_SIZE_GENERAL_PARAMS_ENTRY) 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci#define SJA1105PQRS_SIZE_AVB_PARAMS_DYN_CMD \ 15862306a36Sopenharmony_ci (SJA1105_SIZE_DYN_CMD + SJA1105PQRS_SIZE_AVB_PARAMS_ENTRY) 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci#define SJA1105_SIZE_RETAGGING_DYN_CMD \ 16162306a36Sopenharmony_ci (SJA1105_SIZE_DYN_CMD + SJA1105_SIZE_RETAGGING_ENTRY) 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci#define SJA1105ET_SIZE_CBS_DYN_CMD \ 16462306a36Sopenharmony_ci (SJA1105_SIZE_DYN_CMD + SJA1105ET_SIZE_CBS_ENTRY) 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci#define SJA1105PQRS_SIZE_CBS_DYN_CMD \ 16762306a36Sopenharmony_ci (SJA1105_SIZE_DYN_CMD + SJA1105PQRS_SIZE_CBS_ENTRY) 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci#define SJA1110_SIZE_XMII_PARAMS_DYN_CMD \ 17062306a36Sopenharmony_ci SJA1110_SIZE_XMII_PARAMS_ENTRY 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci#define SJA1110_SIZE_L2_POLICING_DYN_CMD \ 17362306a36Sopenharmony_ci (SJA1105_SIZE_DYN_CMD + SJA1105_SIZE_L2_POLICING_ENTRY) 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci#define SJA1110_SIZE_L2_FORWARDING_PARAMS_DYN_CMD \ 17662306a36Sopenharmony_ci SJA1105_SIZE_L2_FORWARDING_PARAMS_ENTRY 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci#define SJA1105_MAX_DYN_CMD_SIZE \ 17962306a36Sopenharmony_ci SJA1110_SIZE_GENERAL_PARAMS_DYN_CMD 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_cistruct sja1105_dyn_cmd { 18262306a36Sopenharmony_ci bool search; 18362306a36Sopenharmony_ci u64 valid; 18462306a36Sopenharmony_ci u64 rdwrset; 18562306a36Sopenharmony_ci u64 errors; 18662306a36Sopenharmony_ci u64 valident; 18762306a36Sopenharmony_ci u64 index; 18862306a36Sopenharmony_ci}; 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_cienum sja1105_hostcmd { 19162306a36Sopenharmony_ci SJA1105_HOSTCMD_SEARCH = 1, 19262306a36Sopenharmony_ci SJA1105_HOSTCMD_READ = 2, 19362306a36Sopenharmony_ci SJA1105_HOSTCMD_WRITE = 3, 19462306a36Sopenharmony_ci SJA1105_HOSTCMD_INVALIDATE = 4, 19562306a36Sopenharmony_ci}; 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci/* Command and entry overlap */ 19862306a36Sopenharmony_cistatic void 19962306a36Sopenharmony_cisja1105et_vl_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 20062306a36Sopenharmony_ci enum packing_op op) 20162306a36Sopenharmony_ci{ 20262306a36Sopenharmony_ci const int size = SJA1105_SIZE_DYN_CMD; 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci sja1105_packing(buf, &cmd->valid, 31, 31, size, op); 20562306a36Sopenharmony_ci sja1105_packing(buf, &cmd->errors, 30, 30, size, op); 20662306a36Sopenharmony_ci sja1105_packing(buf, &cmd->rdwrset, 29, 29, size, op); 20762306a36Sopenharmony_ci sja1105_packing(buf, &cmd->index, 9, 0, size, op); 20862306a36Sopenharmony_ci} 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci/* Command and entry are separate */ 21162306a36Sopenharmony_cistatic void 21262306a36Sopenharmony_cisja1105pqrs_vl_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 21362306a36Sopenharmony_ci enum packing_op op) 21462306a36Sopenharmony_ci{ 21562306a36Sopenharmony_ci u8 *p = buf + SJA1105_SIZE_VL_LOOKUP_ENTRY; 21662306a36Sopenharmony_ci const int size = SJA1105_SIZE_DYN_CMD; 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci sja1105_packing(p, &cmd->valid, 31, 31, size, op); 21962306a36Sopenharmony_ci sja1105_packing(p, &cmd->errors, 30, 30, size, op); 22062306a36Sopenharmony_ci sja1105_packing(p, &cmd->rdwrset, 29, 29, size, op); 22162306a36Sopenharmony_ci sja1105_packing(p, &cmd->index, 9, 0, size, op); 22262306a36Sopenharmony_ci} 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_cistatic void 22562306a36Sopenharmony_cisja1110_vl_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 22662306a36Sopenharmony_ci enum packing_op op) 22762306a36Sopenharmony_ci{ 22862306a36Sopenharmony_ci u8 *p = buf + SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY; 22962306a36Sopenharmony_ci const int size = SJA1105_SIZE_DYN_CMD; 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci sja1105_packing(p, &cmd->valid, 31, 31, size, op); 23262306a36Sopenharmony_ci sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op); 23362306a36Sopenharmony_ci sja1105_packing(p, &cmd->errors, 29, 29, size, op); 23462306a36Sopenharmony_ci sja1105_packing(p, &cmd->index, 11, 0, size, op); 23562306a36Sopenharmony_ci} 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_cistatic size_t sja1105et_vl_lookup_entry_packing(void *buf, void *entry_ptr, 23862306a36Sopenharmony_ci enum packing_op op) 23962306a36Sopenharmony_ci{ 24062306a36Sopenharmony_ci struct sja1105_vl_lookup_entry *entry = entry_ptr; 24162306a36Sopenharmony_ci const int size = SJA1105ET_SIZE_VL_LOOKUP_DYN_CMD; 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci sja1105_packing(buf, &entry->egrmirr, 21, 17, size, op); 24462306a36Sopenharmony_ci sja1105_packing(buf, &entry->ingrmirr, 16, 16, size, op); 24562306a36Sopenharmony_ci return size; 24662306a36Sopenharmony_ci} 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_cistatic void 24962306a36Sopenharmony_cisja1110_vl_policing_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 25062306a36Sopenharmony_ci enum packing_op op) 25162306a36Sopenharmony_ci{ 25262306a36Sopenharmony_ci u8 *p = buf + SJA1105_SIZE_VL_LOOKUP_ENTRY; 25362306a36Sopenharmony_ci const int size = SJA1105_SIZE_DYN_CMD; 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci sja1105_packing(p, &cmd->valid, 31, 31, size, op); 25662306a36Sopenharmony_ci sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op); 25762306a36Sopenharmony_ci sja1105_packing(p, &cmd->index, 11, 0, size, op); 25862306a36Sopenharmony_ci} 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_cistatic void 26162306a36Sopenharmony_cisja1105pqrs_common_l2_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 26262306a36Sopenharmony_ci enum packing_op op, int entry_size) 26362306a36Sopenharmony_ci{ 26462306a36Sopenharmony_ci const int size = SJA1105_SIZE_DYN_CMD; 26562306a36Sopenharmony_ci u8 *p = buf + entry_size; 26662306a36Sopenharmony_ci u64 hostcmd; 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci sja1105_packing(p, &cmd->valid, 31, 31, size, op); 26962306a36Sopenharmony_ci sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op); 27062306a36Sopenharmony_ci sja1105_packing(p, &cmd->errors, 29, 29, size, op); 27162306a36Sopenharmony_ci sja1105_packing(p, &cmd->valident, 27, 27, size, op); 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci /* VALIDENT is supposed to indicate "keep or not", but in SJA1105 E/T, 27462306a36Sopenharmony_ci * using it to delete a management route was unsupported. UM10944 27562306a36Sopenharmony_ci * said about it: 27662306a36Sopenharmony_ci * 27762306a36Sopenharmony_ci * In case of a write access with the MGMTROUTE flag set, 27862306a36Sopenharmony_ci * the flag will be ignored. It will always be found cleared 27962306a36Sopenharmony_ci * for read accesses with the MGMTROUTE flag set. 28062306a36Sopenharmony_ci * 28162306a36Sopenharmony_ci * SJA1105 P/Q/R/S keeps the same behavior w.r.t. VALIDENT, but there 28262306a36Sopenharmony_ci * is now another flag called HOSTCMD which does more stuff (quoting 28362306a36Sopenharmony_ci * from UM11040): 28462306a36Sopenharmony_ci * 28562306a36Sopenharmony_ci * A write request is accepted only when HOSTCMD is set to write host 28662306a36Sopenharmony_ci * or invalid. A read request is accepted only when HOSTCMD is set to 28762306a36Sopenharmony_ci * search host or read host. 28862306a36Sopenharmony_ci * 28962306a36Sopenharmony_ci * So it is possible to translate a RDWRSET/VALIDENT combination into 29062306a36Sopenharmony_ci * HOSTCMD so that we keep the dynamic command API in place, and 29162306a36Sopenharmony_ci * at the same time achieve compatibility with the management route 29262306a36Sopenharmony_ci * command structure. 29362306a36Sopenharmony_ci */ 29462306a36Sopenharmony_ci if (cmd->rdwrset == SPI_READ) { 29562306a36Sopenharmony_ci if (cmd->search) 29662306a36Sopenharmony_ci hostcmd = SJA1105_HOSTCMD_SEARCH; 29762306a36Sopenharmony_ci else 29862306a36Sopenharmony_ci hostcmd = SJA1105_HOSTCMD_READ; 29962306a36Sopenharmony_ci } else { 30062306a36Sopenharmony_ci /* SPI_WRITE */ 30162306a36Sopenharmony_ci if (cmd->valident) 30262306a36Sopenharmony_ci hostcmd = SJA1105_HOSTCMD_WRITE; 30362306a36Sopenharmony_ci else 30462306a36Sopenharmony_ci hostcmd = SJA1105_HOSTCMD_INVALIDATE; 30562306a36Sopenharmony_ci } 30662306a36Sopenharmony_ci sja1105_packing(p, &hostcmd, 25, 23, size, op); 30762306a36Sopenharmony_ci} 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_cistatic void 31062306a36Sopenharmony_cisja1105pqrs_l2_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 31162306a36Sopenharmony_ci enum packing_op op) 31262306a36Sopenharmony_ci{ 31362306a36Sopenharmony_ci int entry_size = SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY; 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci sja1105pqrs_common_l2_lookup_cmd_packing(buf, cmd, op, entry_size); 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci /* Hack - The hardware takes the 'index' field within 31862306a36Sopenharmony_ci * struct sja1105_l2_lookup_entry as the index on which this command 31962306a36Sopenharmony_ci * will operate. However it will ignore everything else, so 'index' 32062306a36Sopenharmony_ci * is logically part of command but physically part of entry. 32162306a36Sopenharmony_ci * Populate the 'index' entry field from within the command callback, 32262306a36Sopenharmony_ci * such that our API doesn't need to ask for a full-blown entry 32362306a36Sopenharmony_ci * structure when e.g. a delete is requested. 32462306a36Sopenharmony_ci */ 32562306a36Sopenharmony_ci sja1105_packing(buf, &cmd->index, 15, 6, entry_size, op); 32662306a36Sopenharmony_ci} 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_cistatic void 32962306a36Sopenharmony_cisja1110_l2_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 33062306a36Sopenharmony_ci enum packing_op op) 33162306a36Sopenharmony_ci{ 33262306a36Sopenharmony_ci int entry_size = SJA1110_SIZE_L2_LOOKUP_ENTRY; 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci sja1105pqrs_common_l2_lookup_cmd_packing(buf, cmd, op, entry_size); 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci sja1105_packing(buf, &cmd->index, 10, 1, entry_size, op); 33762306a36Sopenharmony_ci} 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci/* The switch is so retarded that it makes our command/entry abstraction 34062306a36Sopenharmony_ci * crumble apart. 34162306a36Sopenharmony_ci * 34262306a36Sopenharmony_ci * On P/Q/R/S, the switch tries to say whether a FDB entry 34362306a36Sopenharmony_ci * is statically programmed or dynamically learned via a flag called LOCKEDS. 34462306a36Sopenharmony_ci * The hardware manual says about this fiels: 34562306a36Sopenharmony_ci * 34662306a36Sopenharmony_ci * On write will specify the format of ENTRY. 34762306a36Sopenharmony_ci * On read the flag will be found cleared at times the VALID flag is found 34862306a36Sopenharmony_ci * set. The flag will also be found cleared in response to a read having the 34962306a36Sopenharmony_ci * MGMTROUTE flag set. In response to a read with the MGMTROUTE flag 35062306a36Sopenharmony_ci * cleared, the flag be set if the most recent access operated on an entry 35162306a36Sopenharmony_ci * that was either loaded by configuration or through dynamic reconfiguration 35262306a36Sopenharmony_ci * (as opposed to automatically learned entries). 35362306a36Sopenharmony_ci * 35462306a36Sopenharmony_ci * The trouble with this flag is that it's part of the *command* to access the 35562306a36Sopenharmony_ci * dynamic interface, and not part of the *entry* retrieved from it. 35662306a36Sopenharmony_ci * Otherwise said, for a sja1105_dynamic_config_read, LOCKEDS is supposed to be 35762306a36Sopenharmony_ci * an output from the switch into the command buffer, and for a 35862306a36Sopenharmony_ci * sja1105_dynamic_config_write, the switch treats LOCKEDS as an input 35962306a36Sopenharmony_ci * (hence we can write either static, or automatically learned entries, from 36062306a36Sopenharmony_ci * the core). 36162306a36Sopenharmony_ci * But the manual contradicts itself in the last phrase where it says that on 36262306a36Sopenharmony_ci * read, LOCKEDS will be set to 1 for all FDB entries written through the 36362306a36Sopenharmony_ci * dynamic interface (therefore, the value of LOCKEDS from the 36462306a36Sopenharmony_ci * sja1105_dynamic_config_write is not really used for anything, it'll store a 36562306a36Sopenharmony_ci * 1 anyway). 36662306a36Sopenharmony_ci * This means you can't really write a FDB entry with LOCKEDS=0 (automatically 36762306a36Sopenharmony_ci * learned) into the switch, which kind of makes sense. 36862306a36Sopenharmony_ci * As for reading through the dynamic interface, it doesn't make too much sense 36962306a36Sopenharmony_ci * to put LOCKEDS into the command, since the switch will inevitably have to 37062306a36Sopenharmony_ci * ignore it (otherwise a command would be like "read the FDB entry 123, but 37162306a36Sopenharmony_ci * only if it's dynamically learned" <- well how am I supposed to know?) and 37262306a36Sopenharmony_ci * just use it as an output buffer for its findings. But guess what... that's 37362306a36Sopenharmony_ci * what the entry buffer is for! 37462306a36Sopenharmony_ci * Unfortunately, what really breaks this abstraction is the fact that it 37562306a36Sopenharmony_ci * wasn't designed having the fact in mind that the switch can output 37662306a36Sopenharmony_ci * entry-related data as writeback through the command buffer. 37762306a36Sopenharmony_ci * However, whether a FDB entry is statically or dynamically learned *is* part 37862306a36Sopenharmony_ci * of the entry and not the command data, no matter what the switch thinks. 37962306a36Sopenharmony_ci * In order to do that, we'll need to wrap around the 38062306a36Sopenharmony_ci * sja1105pqrs_l2_lookup_entry_packing from sja1105_static_config.c, and take 38162306a36Sopenharmony_ci * a peek outside of the caller-supplied @buf (the entry buffer), to reach the 38262306a36Sopenharmony_ci * command buffer. 38362306a36Sopenharmony_ci */ 38462306a36Sopenharmony_cistatic size_t 38562306a36Sopenharmony_cisja1105pqrs_dyn_l2_lookup_entry_packing(void *buf, void *entry_ptr, 38662306a36Sopenharmony_ci enum packing_op op) 38762306a36Sopenharmony_ci{ 38862306a36Sopenharmony_ci struct sja1105_l2_lookup_entry *entry = entry_ptr; 38962306a36Sopenharmony_ci u8 *cmd = buf + SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY; 39062306a36Sopenharmony_ci const int size = SJA1105_SIZE_DYN_CMD; 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci sja1105_packing(cmd, &entry->lockeds, 28, 28, size, op); 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci return sja1105pqrs_l2_lookup_entry_packing(buf, entry_ptr, op); 39562306a36Sopenharmony_ci} 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_cistatic size_t sja1110_dyn_l2_lookup_entry_packing(void *buf, void *entry_ptr, 39862306a36Sopenharmony_ci enum packing_op op) 39962306a36Sopenharmony_ci{ 40062306a36Sopenharmony_ci struct sja1105_l2_lookup_entry *entry = entry_ptr; 40162306a36Sopenharmony_ci u8 *cmd = buf + SJA1110_SIZE_L2_LOOKUP_ENTRY; 40262306a36Sopenharmony_ci const int size = SJA1105_SIZE_DYN_CMD; 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci sja1105_packing(cmd, &entry->lockeds, 28, 28, size, op); 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci return sja1110_l2_lookup_entry_packing(buf, entry_ptr, op); 40762306a36Sopenharmony_ci} 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_cistatic void 41062306a36Sopenharmony_cisja1105et_l2_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 41162306a36Sopenharmony_ci enum packing_op op) 41262306a36Sopenharmony_ci{ 41362306a36Sopenharmony_ci u8 *p = buf + SJA1105ET_SIZE_L2_LOOKUP_ENTRY; 41462306a36Sopenharmony_ci const int size = SJA1105_SIZE_DYN_CMD; 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci sja1105_packing(p, &cmd->valid, 31, 31, size, op); 41762306a36Sopenharmony_ci sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op); 41862306a36Sopenharmony_ci sja1105_packing(p, &cmd->errors, 29, 29, size, op); 41962306a36Sopenharmony_ci sja1105_packing(p, &cmd->valident, 27, 27, size, op); 42062306a36Sopenharmony_ci /* Hack - see comments above. */ 42162306a36Sopenharmony_ci sja1105_packing(buf, &cmd->index, 29, 20, 42262306a36Sopenharmony_ci SJA1105ET_SIZE_L2_LOOKUP_ENTRY, op); 42362306a36Sopenharmony_ci} 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_cistatic size_t sja1105et_dyn_l2_lookup_entry_packing(void *buf, void *entry_ptr, 42662306a36Sopenharmony_ci enum packing_op op) 42762306a36Sopenharmony_ci{ 42862306a36Sopenharmony_ci struct sja1105_l2_lookup_entry *entry = entry_ptr; 42962306a36Sopenharmony_ci u8 *cmd = buf + SJA1105ET_SIZE_L2_LOOKUP_ENTRY; 43062306a36Sopenharmony_ci const int size = SJA1105_SIZE_DYN_CMD; 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci sja1105_packing(cmd, &entry->lockeds, 28, 28, size, op); 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ci return sja1105et_l2_lookup_entry_packing(buf, entry_ptr, op); 43562306a36Sopenharmony_ci} 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_cistatic void 43862306a36Sopenharmony_cisja1105et_mgmt_route_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 43962306a36Sopenharmony_ci enum packing_op op) 44062306a36Sopenharmony_ci{ 44162306a36Sopenharmony_ci u8 *p = buf + SJA1105ET_SIZE_L2_LOOKUP_ENTRY; 44262306a36Sopenharmony_ci u64 mgmtroute = 1; 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ci sja1105et_l2_lookup_cmd_packing(buf, cmd, op); 44562306a36Sopenharmony_ci if (op == PACK) 44662306a36Sopenharmony_ci sja1105_pack(p, &mgmtroute, 26, 26, SJA1105_SIZE_DYN_CMD); 44762306a36Sopenharmony_ci} 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_cistatic size_t sja1105et_mgmt_route_entry_packing(void *buf, void *entry_ptr, 45062306a36Sopenharmony_ci enum packing_op op) 45162306a36Sopenharmony_ci{ 45262306a36Sopenharmony_ci struct sja1105_mgmt_entry *entry = entry_ptr; 45362306a36Sopenharmony_ci const size_t size = SJA1105ET_SIZE_L2_LOOKUP_ENTRY; 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci /* UM10944: To specify if a PTP egress timestamp shall be captured on 45662306a36Sopenharmony_ci * each port upon transmission of the frame, the LSB of VLANID in the 45762306a36Sopenharmony_ci * ENTRY field provided by the host must be set. 45862306a36Sopenharmony_ci * Bit 1 of VLANID then specifies the register where the timestamp for 45962306a36Sopenharmony_ci * this port is stored in. 46062306a36Sopenharmony_ci */ 46162306a36Sopenharmony_ci sja1105_packing(buf, &entry->tsreg, 85, 85, size, op); 46262306a36Sopenharmony_ci sja1105_packing(buf, &entry->takets, 84, 84, size, op); 46362306a36Sopenharmony_ci sja1105_packing(buf, &entry->macaddr, 83, 36, size, op); 46462306a36Sopenharmony_ci sja1105_packing(buf, &entry->destports, 35, 31, size, op); 46562306a36Sopenharmony_ci sja1105_packing(buf, &entry->enfport, 30, 30, size, op); 46662306a36Sopenharmony_ci return size; 46762306a36Sopenharmony_ci} 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_cistatic void 47062306a36Sopenharmony_cisja1105pqrs_mgmt_route_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 47162306a36Sopenharmony_ci enum packing_op op) 47262306a36Sopenharmony_ci{ 47362306a36Sopenharmony_ci u8 *p = buf + SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY; 47462306a36Sopenharmony_ci u64 mgmtroute = 1; 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_ci sja1105pqrs_l2_lookup_cmd_packing(buf, cmd, op); 47762306a36Sopenharmony_ci if (op == PACK) 47862306a36Sopenharmony_ci sja1105_pack(p, &mgmtroute, 26, 26, SJA1105_SIZE_DYN_CMD); 47962306a36Sopenharmony_ci} 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_cistatic size_t sja1105pqrs_mgmt_route_entry_packing(void *buf, void *entry_ptr, 48262306a36Sopenharmony_ci enum packing_op op) 48362306a36Sopenharmony_ci{ 48462306a36Sopenharmony_ci const size_t size = SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY; 48562306a36Sopenharmony_ci struct sja1105_mgmt_entry *entry = entry_ptr; 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci /* In P/Q/R/S, enfport got renamed to mgmtvalid, but its purpose 48862306a36Sopenharmony_ci * is the same (driver uses it to confirm that frame was sent). 48962306a36Sopenharmony_ci * So just keep the name from E/T. 49062306a36Sopenharmony_ci */ 49162306a36Sopenharmony_ci sja1105_packing(buf, &entry->tsreg, 71, 71, size, op); 49262306a36Sopenharmony_ci sja1105_packing(buf, &entry->takets, 70, 70, size, op); 49362306a36Sopenharmony_ci sja1105_packing(buf, &entry->macaddr, 69, 22, size, op); 49462306a36Sopenharmony_ci sja1105_packing(buf, &entry->destports, 21, 17, size, op); 49562306a36Sopenharmony_ci sja1105_packing(buf, &entry->enfport, 16, 16, size, op); 49662306a36Sopenharmony_ci return size; 49762306a36Sopenharmony_ci} 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci/* In E/T, entry is at addresses 0x27-0x28. There is a 4 byte gap at 0x29, 50062306a36Sopenharmony_ci * and command is at 0x2a. Similarly in P/Q/R/S there is a 1 register gap 50162306a36Sopenharmony_ci * between entry (0x2d, 0x2e) and command (0x30). 50262306a36Sopenharmony_ci */ 50362306a36Sopenharmony_cistatic void 50462306a36Sopenharmony_cisja1105_vlan_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 50562306a36Sopenharmony_ci enum packing_op op) 50662306a36Sopenharmony_ci{ 50762306a36Sopenharmony_ci u8 *p = buf + SJA1105_SIZE_VLAN_LOOKUP_ENTRY + 4; 50862306a36Sopenharmony_ci const int size = SJA1105_SIZE_DYN_CMD; 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_ci sja1105_packing(p, &cmd->valid, 31, 31, size, op); 51162306a36Sopenharmony_ci sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op); 51262306a36Sopenharmony_ci sja1105_packing(p, &cmd->valident, 27, 27, size, op); 51362306a36Sopenharmony_ci /* Hack - see comments above, applied for 'vlanid' field of 51462306a36Sopenharmony_ci * struct sja1105_vlan_lookup_entry. 51562306a36Sopenharmony_ci */ 51662306a36Sopenharmony_ci sja1105_packing(buf, &cmd->index, 38, 27, 51762306a36Sopenharmony_ci SJA1105_SIZE_VLAN_LOOKUP_ENTRY, op); 51862306a36Sopenharmony_ci} 51962306a36Sopenharmony_ci 52062306a36Sopenharmony_ci/* In SJA1110 there is no gap between the command and the data, yay... */ 52162306a36Sopenharmony_cistatic void 52262306a36Sopenharmony_cisja1110_vlan_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 52362306a36Sopenharmony_ci enum packing_op op) 52462306a36Sopenharmony_ci{ 52562306a36Sopenharmony_ci u8 *p = buf + SJA1110_SIZE_VLAN_LOOKUP_ENTRY; 52662306a36Sopenharmony_ci const int size = SJA1105_SIZE_DYN_CMD; 52762306a36Sopenharmony_ci u64 type_entry = 0; 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ci sja1105_packing(p, &cmd->valid, 31, 31, size, op); 53062306a36Sopenharmony_ci sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op); 53162306a36Sopenharmony_ci sja1105_packing(p, &cmd->errors, 29, 29, size, op); 53262306a36Sopenharmony_ci /* Hack: treat 'vlanid' field of struct sja1105_vlan_lookup_entry as 53362306a36Sopenharmony_ci * cmd->index. 53462306a36Sopenharmony_ci */ 53562306a36Sopenharmony_ci sja1105_packing(buf, &cmd->index, 38, 27, 53662306a36Sopenharmony_ci SJA1110_SIZE_VLAN_LOOKUP_ENTRY, op); 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_ci /* But the VALIDENT bit has disappeared, now we are supposed to 53962306a36Sopenharmony_ci * invalidate an entry through the TYPE_ENTRY field of the entry.. 54062306a36Sopenharmony_ci * This is a hack to transform the non-zero quality of the TYPE_ENTRY 54162306a36Sopenharmony_ci * field into a VALIDENT bit. 54262306a36Sopenharmony_ci */ 54362306a36Sopenharmony_ci if (op == PACK && !cmd->valident) { 54462306a36Sopenharmony_ci sja1105_packing(buf, &type_entry, 40, 39, 54562306a36Sopenharmony_ci SJA1110_SIZE_VLAN_LOOKUP_ENTRY, PACK); 54662306a36Sopenharmony_ci } else if (op == UNPACK) { 54762306a36Sopenharmony_ci sja1105_packing(buf, &type_entry, 40, 39, 54862306a36Sopenharmony_ci SJA1110_SIZE_VLAN_LOOKUP_ENTRY, UNPACK); 54962306a36Sopenharmony_ci cmd->valident = !!type_entry; 55062306a36Sopenharmony_ci } 55162306a36Sopenharmony_ci} 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_cistatic void 55462306a36Sopenharmony_cisja1105_l2_forwarding_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 55562306a36Sopenharmony_ci enum packing_op op) 55662306a36Sopenharmony_ci{ 55762306a36Sopenharmony_ci u8 *p = buf + SJA1105_SIZE_L2_FORWARDING_ENTRY; 55862306a36Sopenharmony_ci const int size = SJA1105_SIZE_DYN_CMD; 55962306a36Sopenharmony_ci 56062306a36Sopenharmony_ci sja1105_packing(p, &cmd->valid, 31, 31, size, op); 56162306a36Sopenharmony_ci sja1105_packing(p, &cmd->errors, 30, 30, size, op); 56262306a36Sopenharmony_ci sja1105_packing(p, &cmd->rdwrset, 29, 29, size, op); 56362306a36Sopenharmony_ci sja1105_packing(p, &cmd->index, 4, 0, size, op); 56462306a36Sopenharmony_ci} 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_cistatic void 56762306a36Sopenharmony_cisja1110_l2_forwarding_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 56862306a36Sopenharmony_ci enum packing_op op) 56962306a36Sopenharmony_ci{ 57062306a36Sopenharmony_ci u8 *p = buf + SJA1105_SIZE_L2_FORWARDING_ENTRY; 57162306a36Sopenharmony_ci const int size = SJA1105_SIZE_DYN_CMD; 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_ci sja1105_packing(p, &cmd->valid, 31, 31, size, op); 57462306a36Sopenharmony_ci sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op); 57562306a36Sopenharmony_ci sja1105_packing(p, &cmd->errors, 29, 29, size, op); 57662306a36Sopenharmony_ci sja1105_packing(p, &cmd->index, 4, 0, size, op); 57762306a36Sopenharmony_ci} 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_cistatic void 58062306a36Sopenharmony_cisja1105et_mac_config_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 58162306a36Sopenharmony_ci enum packing_op op) 58262306a36Sopenharmony_ci{ 58362306a36Sopenharmony_ci const int size = SJA1105_SIZE_DYN_CMD; 58462306a36Sopenharmony_ci /* Yup, user manual definitions are reversed */ 58562306a36Sopenharmony_ci u8 *reg1 = buf + 4; 58662306a36Sopenharmony_ci 58762306a36Sopenharmony_ci sja1105_packing(reg1, &cmd->valid, 31, 31, size, op); 58862306a36Sopenharmony_ci sja1105_packing(reg1, &cmd->index, 26, 24, size, op); 58962306a36Sopenharmony_ci} 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_cistatic size_t sja1105et_mac_config_entry_packing(void *buf, void *entry_ptr, 59262306a36Sopenharmony_ci enum packing_op op) 59362306a36Sopenharmony_ci{ 59462306a36Sopenharmony_ci const int size = SJA1105ET_SIZE_MAC_CONFIG_DYN_ENTRY; 59562306a36Sopenharmony_ci struct sja1105_mac_config_entry *entry = entry_ptr; 59662306a36Sopenharmony_ci /* Yup, user manual definitions are reversed */ 59762306a36Sopenharmony_ci u8 *reg1 = buf + 4; 59862306a36Sopenharmony_ci u8 *reg2 = buf; 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_ci sja1105_packing(reg1, &entry->speed, 30, 29, size, op); 60162306a36Sopenharmony_ci sja1105_packing(reg1, &entry->drpdtag, 23, 23, size, op); 60262306a36Sopenharmony_ci sja1105_packing(reg1, &entry->drpuntag, 22, 22, size, op); 60362306a36Sopenharmony_ci sja1105_packing(reg1, &entry->retag, 21, 21, size, op); 60462306a36Sopenharmony_ci sja1105_packing(reg1, &entry->dyn_learn, 20, 20, size, op); 60562306a36Sopenharmony_ci sja1105_packing(reg1, &entry->egress, 19, 19, size, op); 60662306a36Sopenharmony_ci sja1105_packing(reg1, &entry->ingress, 18, 18, size, op); 60762306a36Sopenharmony_ci sja1105_packing(reg1, &entry->ing_mirr, 17, 17, size, op); 60862306a36Sopenharmony_ci sja1105_packing(reg1, &entry->egr_mirr, 16, 16, size, op); 60962306a36Sopenharmony_ci sja1105_packing(reg1, &entry->vlanprio, 14, 12, size, op); 61062306a36Sopenharmony_ci sja1105_packing(reg1, &entry->vlanid, 11, 0, size, op); 61162306a36Sopenharmony_ci sja1105_packing(reg2, &entry->tp_delin, 31, 16, size, op); 61262306a36Sopenharmony_ci sja1105_packing(reg2, &entry->tp_delout, 15, 0, size, op); 61362306a36Sopenharmony_ci /* MAC configuration table entries which can't be reconfigured: 61462306a36Sopenharmony_ci * top, base, enabled, ifg, maxage, drpnona664 61562306a36Sopenharmony_ci */ 61662306a36Sopenharmony_ci /* Bogus return value, not used anywhere */ 61762306a36Sopenharmony_ci return 0; 61862306a36Sopenharmony_ci} 61962306a36Sopenharmony_ci 62062306a36Sopenharmony_cistatic void 62162306a36Sopenharmony_cisja1105pqrs_mac_config_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 62262306a36Sopenharmony_ci enum packing_op op) 62362306a36Sopenharmony_ci{ 62462306a36Sopenharmony_ci const int size = SJA1105ET_SIZE_MAC_CONFIG_DYN_ENTRY; 62562306a36Sopenharmony_ci u8 *p = buf + SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY; 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_ci sja1105_packing(p, &cmd->valid, 31, 31, size, op); 62862306a36Sopenharmony_ci sja1105_packing(p, &cmd->errors, 30, 30, size, op); 62962306a36Sopenharmony_ci sja1105_packing(p, &cmd->rdwrset, 29, 29, size, op); 63062306a36Sopenharmony_ci sja1105_packing(p, &cmd->index, 2, 0, size, op); 63162306a36Sopenharmony_ci} 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_cistatic void 63462306a36Sopenharmony_cisja1110_mac_config_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 63562306a36Sopenharmony_ci enum packing_op op) 63662306a36Sopenharmony_ci{ 63762306a36Sopenharmony_ci u8 *p = buf + SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY; 63862306a36Sopenharmony_ci const int size = SJA1105_SIZE_DYN_CMD; 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_ci sja1105_packing(p, &cmd->valid, 31, 31, size, op); 64162306a36Sopenharmony_ci sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op); 64262306a36Sopenharmony_ci sja1105_packing(p, &cmd->errors, 29, 29, size, op); 64362306a36Sopenharmony_ci sja1105_packing(p, &cmd->index, 3, 0, size, op); 64462306a36Sopenharmony_ci} 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_cistatic void 64762306a36Sopenharmony_cisja1105et_l2_lookup_params_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 64862306a36Sopenharmony_ci enum packing_op op) 64962306a36Sopenharmony_ci{ 65062306a36Sopenharmony_ci sja1105_packing(buf, &cmd->valid, 31, 31, 65162306a36Sopenharmony_ci SJA1105ET_SIZE_L2_LOOKUP_PARAMS_DYN_CMD, op); 65262306a36Sopenharmony_ci} 65362306a36Sopenharmony_ci 65462306a36Sopenharmony_cistatic size_t 65562306a36Sopenharmony_cisja1105et_l2_lookup_params_entry_packing(void *buf, void *entry_ptr, 65662306a36Sopenharmony_ci enum packing_op op) 65762306a36Sopenharmony_ci{ 65862306a36Sopenharmony_ci struct sja1105_l2_lookup_params_entry *entry = entry_ptr; 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci sja1105_packing(buf, &entry->poly, 7, 0, 66162306a36Sopenharmony_ci SJA1105ET_SIZE_L2_LOOKUP_PARAMS_DYN_CMD, op); 66262306a36Sopenharmony_ci /* Bogus return value, not used anywhere */ 66362306a36Sopenharmony_ci return 0; 66462306a36Sopenharmony_ci} 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_cistatic void 66762306a36Sopenharmony_cisja1105pqrs_l2_lookup_params_cmd_packing(void *buf, 66862306a36Sopenharmony_ci struct sja1105_dyn_cmd *cmd, 66962306a36Sopenharmony_ci enum packing_op op) 67062306a36Sopenharmony_ci{ 67162306a36Sopenharmony_ci u8 *p = buf + SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_ENTRY; 67262306a36Sopenharmony_ci const int size = SJA1105_SIZE_DYN_CMD; 67362306a36Sopenharmony_ci 67462306a36Sopenharmony_ci sja1105_packing(p, &cmd->valid, 31, 31, size, op); 67562306a36Sopenharmony_ci sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op); 67662306a36Sopenharmony_ci} 67762306a36Sopenharmony_ci 67862306a36Sopenharmony_cistatic void 67962306a36Sopenharmony_cisja1110_l2_lookup_params_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 68062306a36Sopenharmony_ci enum packing_op op) 68162306a36Sopenharmony_ci{ 68262306a36Sopenharmony_ci u8 *p = buf + SJA1110_SIZE_L2_LOOKUP_PARAMS_ENTRY; 68362306a36Sopenharmony_ci const int size = SJA1105_SIZE_DYN_CMD; 68462306a36Sopenharmony_ci 68562306a36Sopenharmony_ci sja1105_packing(p, &cmd->valid, 31, 31, size, op); 68662306a36Sopenharmony_ci sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op); 68762306a36Sopenharmony_ci sja1105_packing(p, &cmd->errors, 29, 29, size, op); 68862306a36Sopenharmony_ci} 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_cistatic void 69162306a36Sopenharmony_cisja1105et_general_params_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 69262306a36Sopenharmony_ci enum packing_op op) 69362306a36Sopenharmony_ci{ 69462306a36Sopenharmony_ci const int size = SJA1105ET_SIZE_GENERAL_PARAMS_DYN_CMD; 69562306a36Sopenharmony_ci 69662306a36Sopenharmony_ci sja1105_packing(buf, &cmd->valid, 31, 31, size, op); 69762306a36Sopenharmony_ci sja1105_packing(buf, &cmd->errors, 30, 30, size, op); 69862306a36Sopenharmony_ci} 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_cistatic size_t 70162306a36Sopenharmony_cisja1105et_general_params_entry_packing(void *buf, void *entry_ptr, 70262306a36Sopenharmony_ci enum packing_op op) 70362306a36Sopenharmony_ci{ 70462306a36Sopenharmony_ci struct sja1105_general_params_entry *entry = entry_ptr; 70562306a36Sopenharmony_ci const int size = SJA1105ET_SIZE_GENERAL_PARAMS_DYN_CMD; 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_ci sja1105_packing(buf, &entry->mirr_port, 2, 0, size, op); 70862306a36Sopenharmony_ci /* Bogus return value, not used anywhere */ 70962306a36Sopenharmony_ci return 0; 71062306a36Sopenharmony_ci} 71162306a36Sopenharmony_ci 71262306a36Sopenharmony_cistatic void 71362306a36Sopenharmony_cisja1105pqrs_general_params_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 71462306a36Sopenharmony_ci enum packing_op op) 71562306a36Sopenharmony_ci{ 71662306a36Sopenharmony_ci u8 *p = buf + SJA1105PQRS_SIZE_GENERAL_PARAMS_ENTRY; 71762306a36Sopenharmony_ci const int size = SJA1105_SIZE_DYN_CMD; 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_ci sja1105_packing(p, &cmd->valid, 31, 31, size, op); 72062306a36Sopenharmony_ci sja1105_packing(p, &cmd->errors, 30, 30, size, op); 72162306a36Sopenharmony_ci sja1105_packing(p, &cmd->rdwrset, 28, 28, size, op); 72262306a36Sopenharmony_ci} 72362306a36Sopenharmony_ci 72462306a36Sopenharmony_cistatic void 72562306a36Sopenharmony_cisja1110_general_params_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 72662306a36Sopenharmony_ci enum packing_op op) 72762306a36Sopenharmony_ci{ 72862306a36Sopenharmony_ci u8 *p = buf + SJA1110_SIZE_GENERAL_PARAMS_ENTRY; 72962306a36Sopenharmony_ci const int size = SJA1105_SIZE_DYN_CMD; 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_ci sja1105_packing(p, &cmd->valid, 31, 31, size, op); 73262306a36Sopenharmony_ci sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op); 73362306a36Sopenharmony_ci sja1105_packing(p, &cmd->errors, 29, 29, size, op); 73462306a36Sopenharmony_ci} 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_cistatic void 73762306a36Sopenharmony_cisja1105pqrs_avb_params_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 73862306a36Sopenharmony_ci enum packing_op op) 73962306a36Sopenharmony_ci{ 74062306a36Sopenharmony_ci u8 *p = buf + SJA1105PQRS_SIZE_AVB_PARAMS_ENTRY; 74162306a36Sopenharmony_ci const int size = SJA1105_SIZE_DYN_CMD; 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_ci sja1105_packing(p, &cmd->valid, 31, 31, size, op); 74462306a36Sopenharmony_ci sja1105_packing(p, &cmd->errors, 30, 30, size, op); 74562306a36Sopenharmony_ci sja1105_packing(p, &cmd->rdwrset, 29, 29, size, op); 74662306a36Sopenharmony_ci} 74762306a36Sopenharmony_ci 74862306a36Sopenharmony_cistatic void 74962306a36Sopenharmony_cisja1105_retagging_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 75062306a36Sopenharmony_ci enum packing_op op) 75162306a36Sopenharmony_ci{ 75262306a36Sopenharmony_ci u8 *p = buf + SJA1105_SIZE_RETAGGING_ENTRY; 75362306a36Sopenharmony_ci const int size = SJA1105_SIZE_DYN_CMD; 75462306a36Sopenharmony_ci 75562306a36Sopenharmony_ci sja1105_packing(p, &cmd->valid, 31, 31, size, op); 75662306a36Sopenharmony_ci sja1105_packing(p, &cmd->errors, 30, 30, size, op); 75762306a36Sopenharmony_ci sja1105_packing(p, &cmd->valident, 29, 29, size, op); 75862306a36Sopenharmony_ci sja1105_packing(p, &cmd->rdwrset, 28, 28, size, op); 75962306a36Sopenharmony_ci sja1105_packing(p, &cmd->index, 5, 0, size, op); 76062306a36Sopenharmony_ci} 76162306a36Sopenharmony_ci 76262306a36Sopenharmony_cistatic void 76362306a36Sopenharmony_cisja1110_retagging_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 76462306a36Sopenharmony_ci enum packing_op op) 76562306a36Sopenharmony_ci{ 76662306a36Sopenharmony_ci u8 *p = buf + SJA1105_SIZE_RETAGGING_ENTRY; 76762306a36Sopenharmony_ci const int size = SJA1105_SIZE_DYN_CMD; 76862306a36Sopenharmony_ci 76962306a36Sopenharmony_ci sja1105_packing(p, &cmd->valid, 31, 31, size, op); 77062306a36Sopenharmony_ci sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op); 77162306a36Sopenharmony_ci sja1105_packing(p, &cmd->errors, 29, 29, size, op); 77262306a36Sopenharmony_ci sja1105_packing(p, &cmd->valident, 28, 28, size, op); 77362306a36Sopenharmony_ci sja1105_packing(p, &cmd->index, 4, 0, size, op); 77462306a36Sopenharmony_ci} 77562306a36Sopenharmony_ci 77662306a36Sopenharmony_cistatic void sja1105et_cbs_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 77762306a36Sopenharmony_ci enum packing_op op) 77862306a36Sopenharmony_ci{ 77962306a36Sopenharmony_ci u8 *p = buf + SJA1105ET_SIZE_CBS_ENTRY; 78062306a36Sopenharmony_ci const int size = SJA1105_SIZE_DYN_CMD; 78162306a36Sopenharmony_ci 78262306a36Sopenharmony_ci sja1105_packing(p, &cmd->valid, 31, 31, size, op); 78362306a36Sopenharmony_ci sja1105_packing(p, &cmd->index, 19, 16, size, op); 78462306a36Sopenharmony_ci} 78562306a36Sopenharmony_ci 78662306a36Sopenharmony_cistatic size_t sja1105et_cbs_entry_packing(void *buf, void *entry_ptr, 78762306a36Sopenharmony_ci enum packing_op op) 78862306a36Sopenharmony_ci{ 78962306a36Sopenharmony_ci const size_t size = SJA1105ET_SIZE_CBS_ENTRY; 79062306a36Sopenharmony_ci struct sja1105_cbs_entry *entry = entry_ptr; 79162306a36Sopenharmony_ci u8 *cmd = buf + size; 79262306a36Sopenharmony_ci u32 *p = buf; 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_ci sja1105_packing(cmd, &entry->port, 5, 3, SJA1105_SIZE_DYN_CMD, op); 79562306a36Sopenharmony_ci sja1105_packing(cmd, &entry->prio, 2, 0, SJA1105_SIZE_DYN_CMD, op); 79662306a36Sopenharmony_ci sja1105_packing(p + 3, &entry->credit_lo, 31, 0, size, op); 79762306a36Sopenharmony_ci sja1105_packing(p + 2, &entry->credit_hi, 31, 0, size, op); 79862306a36Sopenharmony_ci sja1105_packing(p + 1, &entry->send_slope, 31, 0, size, op); 79962306a36Sopenharmony_ci sja1105_packing(p + 0, &entry->idle_slope, 31, 0, size, op); 80062306a36Sopenharmony_ci return size; 80162306a36Sopenharmony_ci} 80262306a36Sopenharmony_ci 80362306a36Sopenharmony_cistatic void sja1105pqrs_cbs_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 80462306a36Sopenharmony_ci enum packing_op op) 80562306a36Sopenharmony_ci{ 80662306a36Sopenharmony_ci u8 *p = buf + SJA1105PQRS_SIZE_CBS_ENTRY; 80762306a36Sopenharmony_ci const int size = SJA1105_SIZE_DYN_CMD; 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_ci sja1105_packing(p, &cmd->valid, 31, 31, size, op); 81062306a36Sopenharmony_ci sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op); 81162306a36Sopenharmony_ci sja1105_packing(p, &cmd->errors, 29, 29, size, op); 81262306a36Sopenharmony_ci sja1105_packing(p, &cmd->index, 3, 0, size, op); 81362306a36Sopenharmony_ci} 81462306a36Sopenharmony_ci 81562306a36Sopenharmony_cistatic void sja1110_cbs_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 81662306a36Sopenharmony_ci enum packing_op op) 81762306a36Sopenharmony_ci{ 81862306a36Sopenharmony_ci u8 *p = buf + SJA1105PQRS_SIZE_CBS_ENTRY; 81962306a36Sopenharmony_ci const int size = SJA1105_SIZE_DYN_CMD; 82062306a36Sopenharmony_ci 82162306a36Sopenharmony_ci sja1105_packing(p, &cmd->valid, 31, 31, size, op); 82262306a36Sopenharmony_ci sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op); 82362306a36Sopenharmony_ci sja1105_packing(p, &cmd->errors, 29, 29, size, op); 82462306a36Sopenharmony_ci sja1105_packing(p, &cmd->index, 7, 0, size, op); 82562306a36Sopenharmony_ci} 82662306a36Sopenharmony_ci 82762306a36Sopenharmony_cistatic size_t sja1105pqrs_cbs_entry_packing(void *buf, void *entry_ptr, 82862306a36Sopenharmony_ci enum packing_op op) 82962306a36Sopenharmony_ci{ 83062306a36Sopenharmony_ci const size_t size = SJA1105PQRS_SIZE_CBS_ENTRY; 83162306a36Sopenharmony_ci struct sja1105_cbs_entry *entry = entry_ptr; 83262306a36Sopenharmony_ci 83362306a36Sopenharmony_ci sja1105_packing(buf, &entry->port, 159, 157, size, op); 83462306a36Sopenharmony_ci sja1105_packing(buf, &entry->prio, 156, 154, size, op); 83562306a36Sopenharmony_ci sja1105_packing(buf, &entry->credit_lo, 153, 122, size, op); 83662306a36Sopenharmony_ci sja1105_packing(buf, &entry->credit_hi, 121, 90, size, op); 83762306a36Sopenharmony_ci sja1105_packing(buf, &entry->send_slope, 89, 58, size, op); 83862306a36Sopenharmony_ci sja1105_packing(buf, &entry->idle_slope, 57, 26, size, op); 83962306a36Sopenharmony_ci return size; 84062306a36Sopenharmony_ci} 84162306a36Sopenharmony_ci 84262306a36Sopenharmony_cistatic size_t sja1110_cbs_entry_packing(void *buf, void *entry_ptr, 84362306a36Sopenharmony_ci enum packing_op op) 84462306a36Sopenharmony_ci{ 84562306a36Sopenharmony_ci const size_t size = SJA1105PQRS_SIZE_CBS_ENTRY; 84662306a36Sopenharmony_ci struct sja1105_cbs_entry *entry = entry_ptr; 84762306a36Sopenharmony_ci u64 entry_type = SJA1110_CBS_SHAPER; 84862306a36Sopenharmony_ci 84962306a36Sopenharmony_ci sja1105_packing(buf, &entry_type, 159, 159, size, op); 85062306a36Sopenharmony_ci sja1105_packing(buf, &entry->credit_lo, 151, 120, size, op); 85162306a36Sopenharmony_ci sja1105_packing(buf, &entry->credit_hi, 119, 88, size, op); 85262306a36Sopenharmony_ci sja1105_packing(buf, &entry->send_slope, 87, 56, size, op); 85362306a36Sopenharmony_ci sja1105_packing(buf, &entry->idle_slope, 55, 24, size, op); 85462306a36Sopenharmony_ci return size; 85562306a36Sopenharmony_ci} 85662306a36Sopenharmony_ci 85762306a36Sopenharmony_cistatic void sja1110_dummy_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 85862306a36Sopenharmony_ci enum packing_op op) 85962306a36Sopenharmony_ci{ 86062306a36Sopenharmony_ci} 86162306a36Sopenharmony_ci 86262306a36Sopenharmony_cistatic void 86362306a36Sopenharmony_cisja1110_l2_policing_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, 86462306a36Sopenharmony_ci enum packing_op op) 86562306a36Sopenharmony_ci{ 86662306a36Sopenharmony_ci u8 *p = buf + SJA1105_SIZE_L2_POLICING_ENTRY; 86762306a36Sopenharmony_ci const int size = SJA1105_SIZE_DYN_CMD; 86862306a36Sopenharmony_ci 86962306a36Sopenharmony_ci sja1105_packing(p, &cmd->valid, 31, 31, size, op); 87062306a36Sopenharmony_ci sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op); 87162306a36Sopenharmony_ci sja1105_packing(p, &cmd->errors, 29, 29, size, op); 87262306a36Sopenharmony_ci sja1105_packing(p, &cmd->index, 6, 0, size, op); 87362306a36Sopenharmony_ci} 87462306a36Sopenharmony_ci 87562306a36Sopenharmony_ci#define OP_READ BIT(0) 87662306a36Sopenharmony_ci#define OP_WRITE BIT(1) 87762306a36Sopenharmony_ci#define OP_DEL BIT(2) 87862306a36Sopenharmony_ci#define OP_SEARCH BIT(3) 87962306a36Sopenharmony_ci#define OP_VALID_ANYWAY BIT(4) 88062306a36Sopenharmony_ci 88162306a36Sopenharmony_ci/* SJA1105E/T: First generation */ 88262306a36Sopenharmony_ciconst struct sja1105_dynamic_table_ops sja1105et_dyn_ops[BLK_IDX_MAX_DYN] = { 88362306a36Sopenharmony_ci [BLK_IDX_VL_LOOKUP] = { 88462306a36Sopenharmony_ci .entry_packing = sja1105et_vl_lookup_entry_packing, 88562306a36Sopenharmony_ci .cmd_packing = sja1105et_vl_lookup_cmd_packing, 88662306a36Sopenharmony_ci .access = OP_WRITE, 88762306a36Sopenharmony_ci .max_entry_count = SJA1105_MAX_VL_LOOKUP_COUNT, 88862306a36Sopenharmony_ci .packed_size = SJA1105ET_SIZE_VL_LOOKUP_DYN_CMD, 88962306a36Sopenharmony_ci .addr = 0x35, 89062306a36Sopenharmony_ci }, 89162306a36Sopenharmony_ci [BLK_IDX_L2_LOOKUP] = { 89262306a36Sopenharmony_ci .entry_packing = sja1105et_dyn_l2_lookup_entry_packing, 89362306a36Sopenharmony_ci .cmd_packing = sja1105et_l2_lookup_cmd_packing, 89462306a36Sopenharmony_ci .access = (OP_READ | OP_WRITE | OP_DEL), 89562306a36Sopenharmony_ci .max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT, 89662306a36Sopenharmony_ci .packed_size = SJA1105ET_SIZE_L2_LOOKUP_DYN_CMD, 89762306a36Sopenharmony_ci .addr = 0x20, 89862306a36Sopenharmony_ci }, 89962306a36Sopenharmony_ci [BLK_IDX_MGMT_ROUTE] = { 90062306a36Sopenharmony_ci .entry_packing = sja1105et_mgmt_route_entry_packing, 90162306a36Sopenharmony_ci .cmd_packing = sja1105et_mgmt_route_cmd_packing, 90262306a36Sopenharmony_ci .access = (OP_READ | OP_WRITE | OP_VALID_ANYWAY), 90362306a36Sopenharmony_ci .max_entry_count = SJA1105_NUM_PORTS, 90462306a36Sopenharmony_ci .packed_size = SJA1105ET_SIZE_L2_LOOKUP_DYN_CMD, 90562306a36Sopenharmony_ci .addr = 0x20, 90662306a36Sopenharmony_ci }, 90762306a36Sopenharmony_ci [BLK_IDX_VLAN_LOOKUP] = { 90862306a36Sopenharmony_ci .entry_packing = sja1105_vlan_lookup_entry_packing, 90962306a36Sopenharmony_ci .cmd_packing = sja1105_vlan_lookup_cmd_packing, 91062306a36Sopenharmony_ci .access = (OP_WRITE | OP_DEL), 91162306a36Sopenharmony_ci .max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT, 91262306a36Sopenharmony_ci .packed_size = SJA1105_SIZE_VLAN_LOOKUP_DYN_CMD, 91362306a36Sopenharmony_ci .addr = 0x27, 91462306a36Sopenharmony_ci }, 91562306a36Sopenharmony_ci [BLK_IDX_L2_FORWARDING] = { 91662306a36Sopenharmony_ci .entry_packing = sja1105_l2_forwarding_entry_packing, 91762306a36Sopenharmony_ci .cmd_packing = sja1105_l2_forwarding_cmd_packing, 91862306a36Sopenharmony_ci .max_entry_count = SJA1105_MAX_L2_FORWARDING_COUNT, 91962306a36Sopenharmony_ci .access = OP_WRITE, 92062306a36Sopenharmony_ci .packed_size = SJA1105_SIZE_L2_FORWARDING_DYN_CMD, 92162306a36Sopenharmony_ci .addr = 0x24, 92262306a36Sopenharmony_ci }, 92362306a36Sopenharmony_ci [BLK_IDX_MAC_CONFIG] = { 92462306a36Sopenharmony_ci .entry_packing = sja1105et_mac_config_entry_packing, 92562306a36Sopenharmony_ci .cmd_packing = sja1105et_mac_config_cmd_packing, 92662306a36Sopenharmony_ci .max_entry_count = SJA1105_MAX_MAC_CONFIG_COUNT, 92762306a36Sopenharmony_ci .access = OP_WRITE, 92862306a36Sopenharmony_ci .packed_size = SJA1105ET_SIZE_MAC_CONFIG_DYN_CMD, 92962306a36Sopenharmony_ci .addr = 0x36, 93062306a36Sopenharmony_ci }, 93162306a36Sopenharmony_ci [BLK_IDX_L2_LOOKUP_PARAMS] = { 93262306a36Sopenharmony_ci .entry_packing = sja1105et_l2_lookup_params_entry_packing, 93362306a36Sopenharmony_ci .cmd_packing = sja1105et_l2_lookup_params_cmd_packing, 93462306a36Sopenharmony_ci .max_entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT, 93562306a36Sopenharmony_ci .access = OP_WRITE, 93662306a36Sopenharmony_ci .packed_size = SJA1105ET_SIZE_L2_LOOKUP_PARAMS_DYN_CMD, 93762306a36Sopenharmony_ci .addr = 0x38, 93862306a36Sopenharmony_ci }, 93962306a36Sopenharmony_ci [BLK_IDX_GENERAL_PARAMS] = { 94062306a36Sopenharmony_ci .entry_packing = sja1105et_general_params_entry_packing, 94162306a36Sopenharmony_ci .cmd_packing = sja1105et_general_params_cmd_packing, 94262306a36Sopenharmony_ci .max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT, 94362306a36Sopenharmony_ci .access = OP_WRITE, 94462306a36Sopenharmony_ci .packed_size = SJA1105ET_SIZE_GENERAL_PARAMS_DYN_CMD, 94562306a36Sopenharmony_ci .addr = 0x34, 94662306a36Sopenharmony_ci }, 94762306a36Sopenharmony_ci [BLK_IDX_RETAGGING] = { 94862306a36Sopenharmony_ci .entry_packing = sja1105_retagging_entry_packing, 94962306a36Sopenharmony_ci .cmd_packing = sja1105_retagging_cmd_packing, 95062306a36Sopenharmony_ci .max_entry_count = SJA1105_MAX_RETAGGING_COUNT, 95162306a36Sopenharmony_ci .access = (OP_WRITE | OP_DEL), 95262306a36Sopenharmony_ci .packed_size = SJA1105_SIZE_RETAGGING_DYN_CMD, 95362306a36Sopenharmony_ci .addr = 0x31, 95462306a36Sopenharmony_ci }, 95562306a36Sopenharmony_ci [BLK_IDX_CBS] = { 95662306a36Sopenharmony_ci .entry_packing = sja1105et_cbs_entry_packing, 95762306a36Sopenharmony_ci .cmd_packing = sja1105et_cbs_cmd_packing, 95862306a36Sopenharmony_ci .max_entry_count = SJA1105ET_MAX_CBS_COUNT, 95962306a36Sopenharmony_ci .access = OP_WRITE, 96062306a36Sopenharmony_ci .packed_size = SJA1105ET_SIZE_CBS_DYN_CMD, 96162306a36Sopenharmony_ci .addr = 0x2c, 96262306a36Sopenharmony_ci }, 96362306a36Sopenharmony_ci}; 96462306a36Sopenharmony_ci 96562306a36Sopenharmony_ci/* SJA1105P/Q/R/S: Second generation */ 96662306a36Sopenharmony_ciconst struct sja1105_dynamic_table_ops sja1105pqrs_dyn_ops[BLK_IDX_MAX_DYN] = { 96762306a36Sopenharmony_ci [BLK_IDX_VL_LOOKUP] = { 96862306a36Sopenharmony_ci .entry_packing = sja1105_vl_lookup_entry_packing, 96962306a36Sopenharmony_ci .cmd_packing = sja1105pqrs_vl_lookup_cmd_packing, 97062306a36Sopenharmony_ci .access = (OP_READ | OP_WRITE), 97162306a36Sopenharmony_ci .max_entry_count = SJA1105_MAX_VL_LOOKUP_COUNT, 97262306a36Sopenharmony_ci .packed_size = SJA1105PQRS_SIZE_VL_LOOKUP_DYN_CMD, 97362306a36Sopenharmony_ci .addr = 0x47, 97462306a36Sopenharmony_ci }, 97562306a36Sopenharmony_ci [BLK_IDX_L2_LOOKUP] = { 97662306a36Sopenharmony_ci .entry_packing = sja1105pqrs_dyn_l2_lookup_entry_packing, 97762306a36Sopenharmony_ci .cmd_packing = sja1105pqrs_l2_lookup_cmd_packing, 97862306a36Sopenharmony_ci .access = (OP_READ | OP_WRITE | OP_DEL | OP_SEARCH), 97962306a36Sopenharmony_ci .max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT, 98062306a36Sopenharmony_ci .packed_size = SJA1105PQRS_SIZE_L2_LOOKUP_DYN_CMD, 98162306a36Sopenharmony_ci .addr = 0x24, 98262306a36Sopenharmony_ci }, 98362306a36Sopenharmony_ci [BLK_IDX_MGMT_ROUTE] = { 98462306a36Sopenharmony_ci .entry_packing = sja1105pqrs_mgmt_route_entry_packing, 98562306a36Sopenharmony_ci .cmd_packing = sja1105pqrs_mgmt_route_cmd_packing, 98662306a36Sopenharmony_ci .access = (OP_READ | OP_WRITE | OP_DEL | OP_SEARCH | OP_VALID_ANYWAY), 98762306a36Sopenharmony_ci .max_entry_count = SJA1105_NUM_PORTS, 98862306a36Sopenharmony_ci .packed_size = SJA1105PQRS_SIZE_L2_LOOKUP_DYN_CMD, 98962306a36Sopenharmony_ci .addr = 0x24, 99062306a36Sopenharmony_ci }, 99162306a36Sopenharmony_ci [BLK_IDX_VLAN_LOOKUP] = { 99262306a36Sopenharmony_ci .entry_packing = sja1105_vlan_lookup_entry_packing, 99362306a36Sopenharmony_ci .cmd_packing = sja1105_vlan_lookup_cmd_packing, 99462306a36Sopenharmony_ci .access = (OP_READ | OP_WRITE | OP_DEL), 99562306a36Sopenharmony_ci .max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT, 99662306a36Sopenharmony_ci .packed_size = SJA1105_SIZE_VLAN_LOOKUP_DYN_CMD, 99762306a36Sopenharmony_ci .addr = 0x2D, 99862306a36Sopenharmony_ci }, 99962306a36Sopenharmony_ci [BLK_IDX_L2_FORWARDING] = { 100062306a36Sopenharmony_ci .entry_packing = sja1105_l2_forwarding_entry_packing, 100162306a36Sopenharmony_ci .cmd_packing = sja1105_l2_forwarding_cmd_packing, 100262306a36Sopenharmony_ci .max_entry_count = SJA1105_MAX_L2_FORWARDING_COUNT, 100362306a36Sopenharmony_ci .access = OP_WRITE, 100462306a36Sopenharmony_ci .packed_size = SJA1105_SIZE_L2_FORWARDING_DYN_CMD, 100562306a36Sopenharmony_ci .addr = 0x2A, 100662306a36Sopenharmony_ci }, 100762306a36Sopenharmony_ci [BLK_IDX_MAC_CONFIG] = { 100862306a36Sopenharmony_ci .entry_packing = sja1105pqrs_mac_config_entry_packing, 100962306a36Sopenharmony_ci .cmd_packing = sja1105pqrs_mac_config_cmd_packing, 101062306a36Sopenharmony_ci .max_entry_count = SJA1105_MAX_MAC_CONFIG_COUNT, 101162306a36Sopenharmony_ci .access = (OP_READ | OP_WRITE), 101262306a36Sopenharmony_ci .packed_size = SJA1105PQRS_SIZE_MAC_CONFIG_DYN_CMD, 101362306a36Sopenharmony_ci .addr = 0x4B, 101462306a36Sopenharmony_ci }, 101562306a36Sopenharmony_ci [BLK_IDX_L2_LOOKUP_PARAMS] = { 101662306a36Sopenharmony_ci .entry_packing = sja1105pqrs_l2_lookup_params_entry_packing, 101762306a36Sopenharmony_ci .cmd_packing = sja1105pqrs_l2_lookup_params_cmd_packing, 101862306a36Sopenharmony_ci .max_entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT, 101962306a36Sopenharmony_ci .access = (OP_READ | OP_WRITE), 102062306a36Sopenharmony_ci .packed_size = SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_DYN_CMD, 102162306a36Sopenharmony_ci .addr = 0x54, 102262306a36Sopenharmony_ci }, 102362306a36Sopenharmony_ci [BLK_IDX_AVB_PARAMS] = { 102462306a36Sopenharmony_ci .entry_packing = sja1105pqrs_avb_params_entry_packing, 102562306a36Sopenharmony_ci .cmd_packing = sja1105pqrs_avb_params_cmd_packing, 102662306a36Sopenharmony_ci .max_entry_count = SJA1105_MAX_AVB_PARAMS_COUNT, 102762306a36Sopenharmony_ci .access = (OP_READ | OP_WRITE), 102862306a36Sopenharmony_ci .packed_size = SJA1105PQRS_SIZE_AVB_PARAMS_DYN_CMD, 102962306a36Sopenharmony_ci .addr = 0x8003, 103062306a36Sopenharmony_ci }, 103162306a36Sopenharmony_ci [BLK_IDX_GENERAL_PARAMS] = { 103262306a36Sopenharmony_ci .entry_packing = sja1105pqrs_general_params_entry_packing, 103362306a36Sopenharmony_ci .cmd_packing = sja1105pqrs_general_params_cmd_packing, 103462306a36Sopenharmony_ci .max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT, 103562306a36Sopenharmony_ci .access = (OP_READ | OP_WRITE), 103662306a36Sopenharmony_ci .packed_size = SJA1105PQRS_SIZE_GENERAL_PARAMS_DYN_CMD, 103762306a36Sopenharmony_ci .addr = 0x3B, 103862306a36Sopenharmony_ci }, 103962306a36Sopenharmony_ci [BLK_IDX_RETAGGING] = { 104062306a36Sopenharmony_ci .entry_packing = sja1105_retagging_entry_packing, 104162306a36Sopenharmony_ci .cmd_packing = sja1105_retagging_cmd_packing, 104262306a36Sopenharmony_ci .max_entry_count = SJA1105_MAX_RETAGGING_COUNT, 104362306a36Sopenharmony_ci .access = (OP_READ | OP_WRITE | OP_DEL), 104462306a36Sopenharmony_ci .packed_size = SJA1105_SIZE_RETAGGING_DYN_CMD, 104562306a36Sopenharmony_ci .addr = 0x38, 104662306a36Sopenharmony_ci }, 104762306a36Sopenharmony_ci [BLK_IDX_CBS] = { 104862306a36Sopenharmony_ci .entry_packing = sja1105pqrs_cbs_entry_packing, 104962306a36Sopenharmony_ci .cmd_packing = sja1105pqrs_cbs_cmd_packing, 105062306a36Sopenharmony_ci .max_entry_count = SJA1105PQRS_MAX_CBS_COUNT, 105162306a36Sopenharmony_ci .access = OP_WRITE, 105262306a36Sopenharmony_ci .packed_size = SJA1105PQRS_SIZE_CBS_DYN_CMD, 105362306a36Sopenharmony_ci .addr = 0x32, 105462306a36Sopenharmony_ci }, 105562306a36Sopenharmony_ci}; 105662306a36Sopenharmony_ci 105762306a36Sopenharmony_ci/* SJA1110: Third generation */ 105862306a36Sopenharmony_ciconst struct sja1105_dynamic_table_ops sja1110_dyn_ops[BLK_IDX_MAX_DYN] = { 105962306a36Sopenharmony_ci [BLK_IDX_VL_LOOKUP] = { 106062306a36Sopenharmony_ci .entry_packing = sja1110_vl_lookup_entry_packing, 106162306a36Sopenharmony_ci .cmd_packing = sja1110_vl_lookup_cmd_packing, 106262306a36Sopenharmony_ci .access = (OP_READ | OP_WRITE | OP_VALID_ANYWAY), 106362306a36Sopenharmony_ci .max_entry_count = SJA1110_MAX_VL_LOOKUP_COUNT, 106462306a36Sopenharmony_ci .packed_size = SJA1105PQRS_SIZE_VL_LOOKUP_DYN_CMD, 106562306a36Sopenharmony_ci .addr = SJA1110_SPI_ADDR(0x124), 106662306a36Sopenharmony_ci }, 106762306a36Sopenharmony_ci [BLK_IDX_VL_POLICING] = { 106862306a36Sopenharmony_ci .entry_packing = sja1110_vl_policing_entry_packing, 106962306a36Sopenharmony_ci .cmd_packing = sja1110_vl_policing_cmd_packing, 107062306a36Sopenharmony_ci .access = (OP_READ | OP_WRITE | OP_VALID_ANYWAY), 107162306a36Sopenharmony_ci .max_entry_count = SJA1110_MAX_VL_POLICING_COUNT, 107262306a36Sopenharmony_ci .packed_size = SJA1110_SIZE_VL_POLICING_DYN_CMD, 107362306a36Sopenharmony_ci .addr = SJA1110_SPI_ADDR(0x310), 107462306a36Sopenharmony_ci }, 107562306a36Sopenharmony_ci [BLK_IDX_L2_LOOKUP] = { 107662306a36Sopenharmony_ci .entry_packing = sja1110_dyn_l2_lookup_entry_packing, 107762306a36Sopenharmony_ci .cmd_packing = sja1110_l2_lookup_cmd_packing, 107862306a36Sopenharmony_ci .access = (OP_READ | OP_WRITE | OP_DEL | OP_SEARCH), 107962306a36Sopenharmony_ci .max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT, 108062306a36Sopenharmony_ci .packed_size = SJA1110_SIZE_L2_LOOKUP_DYN_CMD, 108162306a36Sopenharmony_ci .addr = SJA1110_SPI_ADDR(0x8c), 108262306a36Sopenharmony_ci }, 108362306a36Sopenharmony_ci [BLK_IDX_VLAN_LOOKUP] = { 108462306a36Sopenharmony_ci .entry_packing = sja1110_vlan_lookup_entry_packing, 108562306a36Sopenharmony_ci .cmd_packing = sja1110_vlan_lookup_cmd_packing, 108662306a36Sopenharmony_ci .access = (OP_READ | OP_WRITE | OP_DEL), 108762306a36Sopenharmony_ci .max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT, 108862306a36Sopenharmony_ci .packed_size = SJA1110_SIZE_VLAN_LOOKUP_DYN_CMD, 108962306a36Sopenharmony_ci .addr = SJA1110_SPI_ADDR(0xb4), 109062306a36Sopenharmony_ci }, 109162306a36Sopenharmony_ci [BLK_IDX_L2_FORWARDING] = { 109262306a36Sopenharmony_ci .entry_packing = sja1110_l2_forwarding_entry_packing, 109362306a36Sopenharmony_ci .cmd_packing = sja1110_l2_forwarding_cmd_packing, 109462306a36Sopenharmony_ci .max_entry_count = SJA1110_MAX_L2_FORWARDING_COUNT, 109562306a36Sopenharmony_ci .access = (OP_READ | OP_WRITE | OP_VALID_ANYWAY), 109662306a36Sopenharmony_ci .packed_size = SJA1105_SIZE_L2_FORWARDING_DYN_CMD, 109762306a36Sopenharmony_ci .addr = SJA1110_SPI_ADDR(0xa8), 109862306a36Sopenharmony_ci }, 109962306a36Sopenharmony_ci [BLK_IDX_MAC_CONFIG] = { 110062306a36Sopenharmony_ci .entry_packing = sja1110_mac_config_entry_packing, 110162306a36Sopenharmony_ci .cmd_packing = sja1110_mac_config_cmd_packing, 110262306a36Sopenharmony_ci .max_entry_count = SJA1110_MAX_MAC_CONFIG_COUNT, 110362306a36Sopenharmony_ci .access = (OP_READ | OP_WRITE | OP_VALID_ANYWAY), 110462306a36Sopenharmony_ci .packed_size = SJA1105PQRS_SIZE_MAC_CONFIG_DYN_CMD, 110562306a36Sopenharmony_ci .addr = SJA1110_SPI_ADDR(0x134), 110662306a36Sopenharmony_ci }, 110762306a36Sopenharmony_ci [BLK_IDX_L2_LOOKUP_PARAMS] = { 110862306a36Sopenharmony_ci .entry_packing = sja1110_l2_lookup_params_entry_packing, 110962306a36Sopenharmony_ci .cmd_packing = sja1110_l2_lookup_params_cmd_packing, 111062306a36Sopenharmony_ci .max_entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT, 111162306a36Sopenharmony_ci .access = (OP_READ | OP_WRITE | OP_VALID_ANYWAY), 111262306a36Sopenharmony_ci .packed_size = SJA1110_SIZE_L2_LOOKUP_PARAMS_DYN_CMD, 111362306a36Sopenharmony_ci .addr = SJA1110_SPI_ADDR(0x158), 111462306a36Sopenharmony_ci }, 111562306a36Sopenharmony_ci [BLK_IDX_AVB_PARAMS] = { 111662306a36Sopenharmony_ci .entry_packing = sja1105pqrs_avb_params_entry_packing, 111762306a36Sopenharmony_ci .cmd_packing = sja1105pqrs_avb_params_cmd_packing, 111862306a36Sopenharmony_ci .max_entry_count = SJA1105_MAX_AVB_PARAMS_COUNT, 111962306a36Sopenharmony_ci .access = (OP_READ | OP_WRITE | OP_VALID_ANYWAY), 112062306a36Sopenharmony_ci .packed_size = SJA1105PQRS_SIZE_AVB_PARAMS_DYN_CMD, 112162306a36Sopenharmony_ci .addr = SJA1110_SPI_ADDR(0x2000C), 112262306a36Sopenharmony_ci }, 112362306a36Sopenharmony_ci [BLK_IDX_GENERAL_PARAMS] = { 112462306a36Sopenharmony_ci .entry_packing = sja1110_general_params_entry_packing, 112562306a36Sopenharmony_ci .cmd_packing = sja1110_general_params_cmd_packing, 112662306a36Sopenharmony_ci .max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT, 112762306a36Sopenharmony_ci .access = (OP_READ | OP_WRITE | OP_VALID_ANYWAY), 112862306a36Sopenharmony_ci .packed_size = SJA1110_SIZE_GENERAL_PARAMS_DYN_CMD, 112962306a36Sopenharmony_ci .addr = SJA1110_SPI_ADDR(0xe8), 113062306a36Sopenharmony_ci }, 113162306a36Sopenharmony_ci [BLK_IDX_RETAGGING] = { 113262306a36Sopenharmony_ci .entry_packing = sja1110_retagging_entry_packing, 113362306a36Sopenharmony_ci .cmd_packing = sja1110_retagging_cmd_packing, 113462306a36Sopenharmony_ci .max_entry_count = SJA1105_MAX_RETAGGING_COUNT, 113562306a36Sopenharmony_ci .access = (OP_READ | OP_WRITE | OP_DEL), 113662306a36Sopenharmony_ci .packed_size = SJA1105_SIZE_RETAGGING_DYN_CMD, 113762306a36Sopenharmony_ci .addr = SJA1110_SPI_ADDR(0xdc), 113862306a36Sopenharmony_ci }, 113962306a36Sopenharmony_ci [BLK_IDX_CBS] = { 114062306a36Sopenharmony_ci .entry_packing = sja1110_cbs_entry_packing, 114162306a36Sopenharmony_ci .cmd_packing = sja1110_cbs_cmd_packing, 114262306a36Sopenharmony_ci .max_entry_count = SJA1110_MAX_CBS_COUNT, 114362306a36Sopenharmony_ci .access = (OP_READ | OP_WRITE | OP_VALID_ANYWAY), 114462306a36Sopenharmony_ci .packed_size = SJA1105PQRS_SIZE_CBS_DYN_CMD, 114562306a36Sopenharmony_ci .addr = SJA1110_SPI_ADDR(0xc4), 114662306a36Sopenharmony_ci }, 114762306a36Sopenharmony_ci [BLK_IDX_XMII_PARAMS] = { 114862306a36Sopenharmony_ci .entry_packing = sja1110_xmii_params_entry_packing, 114962306a36Sopenharmony_ci .cmd_packing = sja1110_dummy_cmd_packing, 115062306a36Sopenharmony_ci .max_entry_count = SJA1105_MAX_XMII_PARAMS_COUNT, 115162306a36Sopenharmony_ci .access = (OP_READ | OP_VALID_ANYWAY), 115262306a36Sopenharmony_ci .packed_size = SJA1110_SIZE_XMII_PARAMS_DYN_CMD, 115362306a36Sopenharmony_ci .addr = SJA1110_SPI_ADDR(0x3c), 115462306a36Sopenharmony_ci }, 115562306a36Sopenharmony_ci [BLK_IDX_L2_POLICING] = { 115662306a36Sopenharmony_ci .entry_packing = sja1110_l2_policing_entry_packing, 115762306a36Sopenharmony_ci .cmd_packing = sja1110_l2_policing_cmd_packing, 115862306a36Sopenharmony_ci .max_entry_count = SJA1110_MAX_L2_POLICING_COUNT, 115962306a36Sopenharmony_ci .access = (OP_READ | OP_WRITE | OP_VALID_ANYWAY), 116062306a36Sopenharmony_ci .packed_size = SJA1110_SIZE_L2_POLICING_DYN_CMD, 116162306a36Sopenharmony_ci .addr = SJA1110_SPI_ADDR(0x2fc), 116262306a36Sopenharmony_ci }, 116362306a36Sopenharmony_ci [BLK_IDX_L2_FORWARDING_PARAMS] = { 116462306a36Sopenharmony_ci .entry_packing = sja1110_l2_forwarding_params_entry_packing, 116562306a36Sopenharmony_ci .cmd_packing = sja1110_dummy_cmd_packing, 116662306a36Sopenharmony_ci .max_entry_count = SJA1105_MAX_L2_FORWARDING_PARAMS_COUNT, 116762306a36Sopenharmony_ci .access = (OP_READ | OP_VALID_ANYWAY), 116862306a36Sopenharmony_ci .packed_size = SJA1110_SIZE_L2_FORWARDING_PARAMS_DYN_CMD, 116962306a36Sopenharmony_ci .addr = SJA1110_SPI_ADDR(0x20000), 117062306a36Sopenharmony_ci }, 117162306a36Sopenharmony_ci}; 117262306a36Sopenharmony_ci 117362306a36Sopenharmony_ci#define SJA1105_DYNAMIC_CONFIG_SLEEP_US 10 117462306a36Sopenharmony_ci#define SJA1105_DYNAMIC_CONFIG_TIMEOUT_US 100000 117562306a36Sopenharmony_ci 117662306a36Sopenharmony_cistatic int 117762306a36Sopenharmony_cisja1105_dynamic_config_poll_valid(struct sja1105_private *priv, 117862306a36Sopenharmony_ci const struct sja1105_dynamic_table_ops *ops, 117962306a36Sopenharmony_ci void *entry, bool check_valident, 118062306a36Sopenharmony_ci bool check_errors) 118162306a36Sopenharmony_ci{ 118262306a36Sopenharmony_ci u8 packed_buf[SJA1105_MAX_DYN_CMD_SIZE] = {}; 118362306a36Sopenharmony_ci struct sja1105_dyn_cmd cmd = {}; 118462306a36Sopenharmony_ci int rc; 118562306a36Sopenharmony_ci 118662306a36Sopenharmony_ci /* Read back the whole entry + command structure. */ 118762306a36Sopenharmony_ci rc = sja1105_xfer_buf(priv, SPI_READ, ops->addr, packed_buf, 118862306a36Sopenharmony_ci ops->packed_size); 118962306a36Sopenharmony_ci if (rc) 119062306a36Sopenharmony_ci return rc; 119162306a36Sopenharmony_ci 119262306a36Sopenharmony_ci /* Unpack the command structure, and return it to the caller in case it 119362306a36Sopenharmony_ci * needs to perform further checks on it (VALIDENT). 119462306a36Sopenharmony_ci */ 119562306a36Sopenharmony_ci ops->cmd_packing(packed_buf, &cmd, UNPACK); 119662306a36Sopenharmony_ci 119762306a36Sopenharmony_ci /* Hardware hasn't cleared VALID => still working on it */ 119862306a36Sopenharmony_ci if (cmd.valid) 119962306a36Sopenharmony_ci return -EAGAIN; 120062306a36Sopenharmony_ci 120162306a36Sopenharmony_ci if (check_valident && !cmd.valident && !(ops->access & OP_VALID_ANYWAY)) 120262306a36Sopenharmony_ci return -ENOENT; 120362306a36Sopenharmony_ci 120462306a36Sopenharmony_ci if (check_errors && cmd.errors) 120562306a36Sopenharmony_ci return -EINVAL; 120662306a36Sopenharmony_ci 120762306a36Sopenharmony_ci /* Don't dereference possibly NULL pointer - maybe caller 120862306a36Sopenharmony_ci * only wanted to see whether the entry existed or not. 120962306a36Sopenharmony_ci */ 121062306a36Sopenharmony_ci if (entry) 121162306a36Sopenharmony_ci ops->entry_packing(packed_buf, entry, UNPACK); 121262306a36Sopenharmony_ci 121362306a36Sopenharmony_ci return 0; 121462306a36Sopenharmony_ci} 121562306a36Sopenharmony_ci 121662306a36Sopenharmony_ci/* Poll the dynamic config entry's control area until the hardware has 121762306a36Sopenharmony_ci * cleared the VALID bit, which means we have confirmation that it has 121862306a36Sopenharmony_ci * finished processing the command. 121962306a36Sopenharmony_ci */ 122062306a36Sopenharmony_cistatic int 122162306a36Sopenharmony_cisja1105_dynamic_config_wait_complete(struct sja1105_private *priv, 122262306a36Sopenharmony_ci const struct sja1105_dynamic_table_ops *ops, 122362306a36Sopenharmony_ci void *entry, bool check_valident, 122462306a36Sopenharmony_ci bool check_errors) 122562306a36Sopenharmony_ci{ 122662306a36Sopenharmony_ci int err, rc; 122762306a36Sopenharmony_ci 122862306a36Sopenharmony_ci err = read_poll_timeout(sja1105_dynamic_config_poll_valid, 122962306a36Sopenharmony_ci rc, rc != -EAGAIN, 123062306a36Sopenharmony_ci SJA1105_DYNAMIC_CONFIG_SLEEP_US, 123162306a36Sopenharmony_ci SJA1105_DYNAMIC_CONFIG_TIMEOUT_US, 123262306a36Sopenharmony_ci false, priv, ops, entry, check_valident, 123362306a36Sopenharmony_ci check_errors); 123462306a36Sopenharmony_ci return err < 0 ? err : rc; 123562306a36Sopenharmony_ci} 123662306a36Sopenharmony_ci 123762306a36Sopenharmony_ci/* Provides read access to the settings through the dynamic interface 123862306a36Sopenharmony_ci * of the switch. 123962306a36Sopenharmony_ci * @blk_idx is used as key to select from the sja1105_dynamic_table_ops. 124062306a36Sopenharmony_ci * The selection is limited by the hardware in respect to which 124162306a36Sopenharmony_ci * configuration blocks can be read through the dynamic interface. 124262306a36Sopenharmony_ci * @index is used to retrieve a particular table entry. If negative, 124362306a36Sopenharmony_ci * (and if the @blk_idx supports the searching operation) a search 124462306a36Sopenharmony_ci * is performed by the @entry parameter. 124562306a36Sopenharmony_ci * @entry Type-casted to an unpacked structure that holds a table entry 124662306a36Sopenharmony_ci * of the type specified in @blk_idx. 124762306a36Sopenharmony_ci * Usually an output argument. If @index is negative, then this 124862306a36Sopenharmony_ci * argument is used as input/output: it should be pre-populated 124962306a36Sopenharmony_ci * with the element to search for. Entries which support the 125062306a36Sopenharmony_ci * search operation will have an "index" field (not the @index 125162306a36Sopenharmony_ci * argument to this function) and that is where the found index 125262306a36Sopenharmony_ci * will be returned (or left unmodified - thus negative - if not 125362306a36Sopenharmony_ci * found). 125462306a36Sopenharmony_ci */ 125562306a36Sopenharmony_ciint sja1105_dynamic_config_read(struct sja1105_private *priv, 125662306a36Sopenharmony_ci enum sja1105_blk_idx blk_idx, 125762306a36Sopenharmony_ci int index, void *entry) 125862306a36Sopenharmony_ci{ 125962306a36Sopenharmony_ci const struct sja1105_dynamic_table_ops *ops; 126062306a36Sopenharmony_ci struct sja1105_dyn_cmd cmd = {0}; 126162306a36Sopenharmony_ci /* SPI payload buffer */ 126262306a36Sopenharmony_ci u8 packed_buf[SJA1105_MAX_DYN_CMD_SIZE] = {0}; 126362306a36Sopenharmony_ci int rc; 126462306a36Sopenharmony_ci 126562306a36Sopenharmony_ci if (blk_idx >= BLK_IDX_MAX_DYN) 126662306a36Sopenharmony_ci return -ERANGE; 126762306a36Sopenharmony_ci 126862306a36Sopenharmony_ci ops = &priv->info->dyn_ops[blk_idx]; 126962306a36Sopenharmony_ci 127062306a36Sopenharmony_ci if (index >= 0 && index >= ops->max_entry_count) 127162306a36Sopenharmony_ci return -ERANGE; 127262306a36Sopenharmony_ci if (index < 0 && !(ops->access & OP_SEARCH)) 127362306a36Sopenharmony_ci return -EOPNOTSUPP; 127462306a36Sopenharmony_ci if (!(ops->access & OP_READ)) 127562306a36Sopenharmony_ci return -EOPNOTSUPP; 127662306a36Sopenharmony_ci if (ops->packed_size > SJA1105_MAX_DYN_CMD_SIZE) 127762306a36Sopenharmony_ci return -ERANGE; 127862306a36Sopenharmony_ci if (!ops->cmd_packing) 127962306a36Sopenharmony_ci return -EOPNOTSUPP; 128062306a36Sopenharmony_ci if (!ops->entry_packing) 128162306a36Sopenharmony_ci return -EOPNOTSUPP; 128262306a36Sopenharmony_ci 128362306a36Sopenharmony_ci cmd.valid = true; /* Trigger action on table entry */ 128462306a36Sopenharmony_ci cmd.rdwrset = SPI_READ; /* Action is read */ 128562306a36Sopenharmony_ci if (index < 0) { 128662306a36Sopenharmony_ci /* Avoid copying a signed negative number to an u64 */ 128762306a36Sopenharmony_ci cmd.index = 0; 128862306a36Sopenharmony_ci cmd.search = true; 128962306a36Sopenharmony_ci } else { 129062306a36Sopenharmony_ci cmd.index = index; 129162306a36Sopenharmony_ci cmd.search = false; 129262306a36Sopenharmony_ci } 129362306a36Sopenharmony_ci cmd.valident = true; 129462306a36Sopenharmony_ci ops->cmd_packing(packed_buf, &cmd, PACK); 129562306a36Sopenharmony_ci 129662306a36Sopenharmony_ci if (cmd.search) 129762306a36Sopenharmony_ci ops->entry_packing(packed_buf, entry, PACK); 129862306a36Sopenharmony_ci 129962306a36Sopenharmony_ci /* Send SPI write operation: read config table entry */ 130062306a36Sopenharmony_ci mutex_lock(&priv->dynamic_config_lock); 130162306a36Sopenharmony_ci rc = sja1105_xfer_buf(priv, SPI_WRITE, ops->addr, packed_buf, 130262306a36Sopenharmony_ci ops->packed_size); 130362306a36Sopenharmony_ci if (rc < 0) 130462306a36Sopenharmony_ci goto out; 130562306a36Sopenharmony_ci 130662306a36Sopenharmony_ci rc = sja1105_dynamic_config_wait_complete(priv, ops, entry, true, false); 130762306a36Sopenharmony_ciout: 130862306a36Sopenharmony_ci mutex_unlock(&priv->dynamic_config_lock); 130962306a36Sopenharmony_ci 131062306a36Sopenharmony_ci return rc; 131162306a36Sopenharmony_ci} 131262306a36Sopenharmony_ci 131362306a36Sopenharmony_ciint sja1105_dynamic_config_write(struct sja1105_private *priv, 131462306a36Sopenharmony_ci enum sja1105_blk_idx blk_idx, 131562306a36Sopenharmony_ci int index, void *entry, bool keep) 131662306a36Sopenharmony_ci{ 131762306a36Sopenharmony_ci const struct sja1105_dynamic_table_ops *ops; 131862306a36Sopenharmony_ci struct sja1105_dyn_cmd cmd = {0}; 131962306a36Sopenharmony_ci /* SPI payload buffer */ 132062306a36Sopenharmony_ci u8 packed_buf[SJA1105_MAX_DYN_CMD_SIZE] = {0}; 132162306a36Sopenharmony_ci int rc; 132262306a36Sopenharmony_ci 132362306a36Sopenharmony_ci if (blk_idx >= BLK_IDX_MAX_DYN) 132462306a36Sopenharmony_ci return -ERANGE; 132562306a36Sopenharmony_ci 132662306a36Sopenharmony_ci ops = &priv->info->dyn_ops[blk_idx]; 132762306a36Sopenharmony_ci 132862306a36Sopenharmony_ci if (index >= ops->max_entry_count) 132962306a36Sopenharmony_ci return -ERANGE; 133062306a36Sopenharmony_ci if (index < 0) 133162306a36Sopenharmony_ci return -ERANGE; 133262306a36Sopenharmony_ci if (!(ops->access & OP_WRITE)) 133362306a36Sopenharmony_ci return -EOPNOTSUPP; 133462306a36Sopenharmony_ci if (!keep && !(ops->access & OP_DEL)) 133562306a36Sopenharmony_ci return -EOPNOTSUPP; 133662306a36Sopenharmony_ci if (ops->packed_size > SJA1105_MAX_DYN_CMD_SIZE) 133762306a36Sopenharmony_ci return -ERANGE; 133862306a36Sopenharmony_ci 133962306a36Sopenharmony_ci cmd.valident = keep; /* If false, deletes entry */ 134062306a36Sopenharmony_ci cmd.valid = true; /* Trigger action on table entry */ 134162306a36Sopenharmony_ci cmd.rdwrset = SPI_WRITE; /* Action is write */ 134262306a36Sopenharmony_ci cmd.index = index; 134362306a36Sopenharmony_ci 134462306a36Sopenharmony_ci if (!ops->cmd_packing) 134562306a36Sopenharmony_ci return -EOPNOTSUPP; 134662306a36Sopenharmony_ci ops->cmd_packing(packed_buf, &cmd, PACK); 134762306a36Sopenharmony_ci 134862306a36Sopenharmony_ci if (!ops->entry_packing) 134962306a36Sopenharmony_ci return -EOPNOTSUPP; 135062306a36Sopenharmony_ci /* Don't dereference potentially NULL pointer if just 135162306a36Sopenharmony_ci * deleting a table entry is what was requested. For cases 135262306a36Sopenharmony_ci * where 'index' field is physically part of entry structure, 135362306a36Sopenharmony_ci * and needed here, we deal with that in the cmd_packing callback. 135462306a36Sopenharmony_ci */ 135562306a36Sopenharmony_ci if (keep) 135662306a36Sopenharmony_ci ops->entry_packing(packed_buf, entry, PACK); 135762306a36Sopenharmony_ci 135862306a36Sopenharmony_ci /* Send SPI write operation: read config table entry */ 135962306a36Sopenharmony_ci mutex_lock(&priv->dynamic_config_lock); 136062306a36Sopenharmony_ci rc = sja1105_xfer_buf(priv, SPI_WRITE, ops->addr, packed_buf, 136162306a36Sopenharmony_ci ops->packed_size); 136262306a36Sopenharmony_ci if (rc < 0) 136362306a36Sopenharmony_ci goto out; 136462306a36Sopenharmony_ci 136562306a36Sopenharmony_ci rc = sja1105_dynamic_config_wait_complete(priv, ops, NULL, false, true); 136662306a36Sopenharmony_ciout: 136762306a36Sopenharmony_ci mutex_unlock(&priv->dynamic_config_lock); 136862306a36Sopenharmony_ci 136962306a36Sopenharmony_ci return rc; 137062306a36Sopenharmony_ci} 137162306a36Sopenharmony_ci 137262306a36Sopenharmony_cistatic u8 sja1105_crc8_add(u8 crc, u8 byte, u8 poly) 137362306a36Sopenharmony_ci{ 137462306a36Sopenharmony_ci int i; 137562306a36Sopenharmony_ci 137662306a36Sopenharmony_ci for (i = 0; i < 8; i++) { 137762306a36Sopenharmony_ci if ((crc ^ byte) & (1 << 7)) { 137862306a36Sopenharmony_ci crc <<= 1; 137962306a36Sopenharmony_ci crc ^= poly; 138062306a36Sopenharmony_ci } else { 138162306a36Sopenharmony_ci crc <<= 1; 138262306a36Sopenharmony_ci } 138362306a36Sopenharmony_ci byte <<= 1; 138462306a36Sopenharmony_ci } 138562306a36Sopenharmony_ci return crc; 138662306a36Sopenharmony_ci} 138762306a36Sopenharmony_ci 138862306a36Sopenharmony_ci/* CRC8 algorithm with non-reversed input, non-reversed output, 138962306a36Sopenharmony_ci * no input xor and no output xor. Code customized for receiving 139062306a36Sopenharmony_ci * the SJA1105 E/T FDB keys (vlanid, macaddr) as input. CRC polynomial 139162306a36Sopenharmony_ci * is also received as argument in the Koopman notation that the switch 139262306a36Sopenharmony_ci * hardware stores it in. 139362306a36Sopenharmony_ci */ 139462306a36Sopenharmony_ciu8 sja1105et_fdb_hash(struct sja1105_private *priv, const u8 *addr, u16 vid) 139562306a36Sopenharmony_ci{ 139662306a36Sopenharmony_ci struct sja1105_l2_lookup_params_entry *l2_lookup_params = 139762306a36Sopenharmony_ci priv->static_config.tables[BLK_IDX_L2_LOOKUP_PARAMS].entries; 139862306a36Sopenharmony_ci u64 input, poly_koopman = l2_lookup_params->poly; 139962306a36Sopenharmony_ci /* Convert polynomial from Koopman to 'normal' notation */ 140062306a36Sopenharmony_ci u8 poly = (u8)(1 + (poly_koopman << 1)); 140162306a36Sopenharmony_ci u8 crc = 0; /* seed */ 140262306a36Sopenharmony_ci int i; 140362306a36Sopenharmony_ci 140462306a36Sopenharmony_ci input = ((u64)vid << 48) | ether_addr_to_u64(addr); 140562306a36Sopenharmony_ci 140662306a36Sopenharmony_ci /* Mask the eight bytes starting from MSB one at a time */ 140762306a36Sopenharmony_ci for (i = 56; i >= 0; i -= 8) { 140862306a36Sopenharmony_ci u8 byte = (input & (0xffull << i)) >> i; 140962306a36Sopenharmony_ci 141062306a36Sopenharmony_ci crc = sja1105_crc8_add(crc, byte, poly); 141162306a36Sopenharmony_ci } 141262306a36Sopenharmony_ci return crc; 141362306a36Sopenharmony_ci} 1414