linux/drivers/net/dsa/sja1105/sja1105_dynamic_config.c
<<
>>
Prefs
   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_SIZE_MAC_CONFIG_DYN_ENTRY                     \
 101        SJA1105_SIZE_DYN_CMD
 102
 103#define SJA1105ET_SIZE_L2_LOOKUP_DYN_CMD                        \
 104        (SJA1105_SIZE_DYN_CMD + SJA1105ET_SIZE_L2_LOOKUP_ENTRY)
 105
 106#define SJA1105PQRS_SIZE_L2_LOOKUP_DYN_CMD                      \
 107        (SJA1105_SIZE_DYN_CMD + SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY)
 108
 109#define SJA1105_SIZE_VLAN_LOOKUP_DYN_CMD                        \
 110        (SJA1105_SIZE_DYN_CMD + 4 + SJA1105_SIZE_VLAN_LOOKUP_ENTRY)
 111
 112#define SJA1105_SIZE_L2_FORWARDING_DYN_CMD                      \
 113        (SJA1105_SIZE_DYN_CMD + SJA1105_SIZE_L2_FORWARDING_ENTRY)
 114
 115#define SJA1105ET_SIZE_MAC_CONFIG_DYN_CMD                       \
 116        (SJA1105_SIZE_DYN_CMD + SJA1105ET_SIZE_MAC_CONFIG_DYN_ENTRY)
 117
 118#define SJA1105PQRS_SIZE_MAC_CONFIG_DYN_CMD                     \
 119        (SJA1105_SIZE_DYN_CMD + SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY)
 120
 121#define SJA1105ET_SIZE_L2_LOOKUP_PARAMS_DYN_CMD                 \
 122        SJA1105_SIZE_DYN_CMD
 123
 124#define SJA1105ET_SIZE_GENERAL_PARAMS_DYN_CMD                   \
 125        SJA1105_SIZE_DYN_CMD
 126
 127#define SJA1105_MAX_DYN_CMD_SIZE                                \
 128        SJA1105PQRS_SIZE_MAC_CONFIG_DYN_CMD
 129
 130struct sja1105_dyn_cmd {
 131        bool search;
 132        u64 valid;
 133        u64 rdwrset;
 134        u64 errors;
 135        u64 valident;
 136        u64 index;
 137};
 138
 139enum sja1105_hostcmd {
 140        SJA1105_HOSTCMD_SEARCH = 1,
 141        SJA1105_HOSTCMD_READ = 2,
 142        SJA1105_HOSTCMD_WRITE = 3,
 143        SJA1105_HOSTCMD_INVALIDATE = 4,
 144};
 145
 146static void
 147sja1105pqrs_l2_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
 148                                  enum packing_op op)
 149{
 150        u8 *p = buf + SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY;
 151        const int size = SJA1105_SIZE_DYN_CMD;
 152        u64 hostcmd;
 153
 154        sja1105_packing(p, &cmd->valid,    31, 31, size, op);
 155        sja1105_packing(p, &cmd->rdwrset,  30, 30, size, op);
 156        sja1105_packing(p, &cmd->errors,   29, 29, size, op);
 157        sja1105_packing(p, &cmd->valident, 27, 27, size, op);
 158
 159        /* VALIDENT is supposed to indicate "keep or not", but in SJA1105 E/T,
 160         * using it to delete a management route was unsupported. UM10944
 161         * said about it:
 162         *
 163         *   In case of a write access with the MGMTROUTE flag set,
 164         *   the flag will be ignored. It will always be found cleared
 165         *   for read accesses with the MGMTROUTE flag set.
 166         *
 167         * SJA1105 P/Q/R/S keeps the same behavior w.r.t. VALIDENT, but there
 168         * is now another flag called HOSTCMD which does more stuff (quoting
 169         * from UM11040):
 170         *
 171         *   A write request is accepted only when HOSTCMD is set to write host
 172         *   or invalid. A read request is accepted only when HOSTCMD is set to
 173         *   search host or read host.
 174         *
 175         * So it is possible to translate a RDWRSET/VALIDENT combination into
 176         * HOSTCMD so that we keep the dynamic command API in place, and
 177         * at the same time achieve compatibility with the management route
 178         * command structure.
 179         */
 180        if (cmd->rdwrset == SPI_READ) {
 181                if (cmd->search)
 182                        hostcmd = SJA1105_HOSTCMD_SEARCH;
 183                else
 184                        hostcmd = SJA1105_HOSTCMD_READ;
 185        } else {
 186                /* SPI_WRITE */
 187                if (cmd->valident)
 188                        hostcmd = SJA1105_HOSTCMD_WRITE;
 189                else
 190                        hostcmd = SJA1105_HOSTCMD_INVALIDATE;
 191        }
 192        sja1105_packing(p, &hostcmd, 25, 23, size, op);
 193
 194        /* Hack - The hardware takes the 'index' field within
 195         * struct sja1105_l2_lookup_entry as the index on which this command
 196         * will operate. However it will ignore everything else, so 'index'
 197         * is logically part of command but physically part of entry.
 198         * Populate the 'index' entry field from within the command callback,
 199         * such that our API doesn't need to ask for a full-blown entry
 200         * structure when e.g. a delete is requested.
 201         */
 202        sja1105_packing(buf, &cmd->index, 15, 6,
 203                        SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY, op);
 204}
 205
 206/* The switch is so retarded that it makes our command/entry abstraction
 207 * crumble apart.
 208 *
 209 * On P/Q/R/S, the switch tries to say whether a FDB entry
 210 * is statically programmed or dynamically learned via a flag called LOCKEDS.
 211 * The hardware manual says about this fiels:
 212 *
 213 *   On write will specify the format of ENTRY.
 214 *   On read the flag will be found cleared at times the VALID flag is found
 215 *   set.  The flag will also be found cleared in response to a read having the
 216 *   MGMTROUTE flag set.  In response to a read with the MGMTROUTE flag
 217 *   cleared, the flag be set if the most recent access operated on an entry
 218 *   that was either loaded by configuration or through dynamic reconfiguration
 219 *   (as opposed to automatically learned entries).
 220 *
 221 * The trouble with this flag is that it's part of the *command* to access the
 222 * dynamic interface, and not part of the *entry* retrieved from it.
 223 * Otherwise said, for a sja1105_dynamic_config_read, LOCKEDS is supposed to be
 224 * an output from the switch into the command buffer, and for a
 225 * sja1105_dynamic_config_write, the switch treats LOCKEDS as an input
 226 * (hence we can write either static, or automatically learned entries, from
 227 * the core).
 228 * But the manual contradicts itself in the last phrase where it says that on
 229 * read, LOCKEDS will be set to 1 for all FDB entries written through the
 230 * dynamic interface (therefore, the value of LOCKEDS from the
 231 * sja1105_dynamic_config_write is not really used for anything, it'll store a
 232 * 1 anyway).
 233 * This means you can't really write a FDB entry with LOCKEDS=0 (automatically
 234 * learned) into the switch, which kind of makes sense.
 235 * As for reading through the dynamic interface, it doesn't make too much sense
 236 * to put LOCKEDS into the command, since the switch will inevitably have to
 237 * ignore it (otherwise a command would be like "read the FDB entry 123, but
 238 * only if it's dynamically learned" <- well how am I supposed to know?) and
 239 * just use it as an output buffer for its findings. But guess what... that's
 240 * what the entry buffer is for!
 241 * Unfortunately, what really breaks this abstraction is the fact that it
 242 * wasn't designed having the fact in mind that the switch can output
 243 * entry-related data as writeback through the command buffer.
 244 * However, whether a FDB entry is statically or dynamically learned *is* part
 245 * of the entry and not the command data, no matter what the switch thinks.
 246 * In order to do that, we'll need to wrap around the
 247 * sja1105pqrs_l2_lookup_entry_packing from sja1105_static_config.c, and take
 248 * a peek outside of the caller-supplied @buf (the entry buffer), to reach the
 249 * command buffer.
 250 */
 251static size_t
 252sja1105pqrs_dyn_l2_lookup_entry_packing(void *buf, void *entry_ptr,
 253                                        enum packing_op op)
 254{
 255        struct sja1105_l2_lookup_entry *entry = entry_ptr;
 256        u8 *cmd = buf + SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY;
 257        const int size = SJA1105_SIZE_DYN_CMD;
 258
 259        sja1105_packing(cmd, &entry->lockeds, 28, 28, size, op);
 260
 261        return sja1105pqrs_l2_lookup_entry_packing(buf, entry_ptr, op);
 262}
 263
 264static void
 265sja1105et_l2_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
 266                                enum packing_op op)
 267{
 268        u8 *p = buf + SJA1105ET_SIZE_L2_LOOKUP_ENTRY;
 269        const int size = SJA1105_SIZE_DYN_CMD;
 270
 271        sja1105_packing(p, &cmd->valid,    31, 31, size, op);
 272        sja1105_packing(p, &cmd->rdwrset,  30, 30, size, op);
 273        sja1105_packing(p, &cmd->errors,   29, 29, size, op);
 274        sja1105_packing(p, &cmd->valident, 27, 27, size, op);
 275        /* Hack - see comments above. */
 276        sja1105_packing(buf, &cmd->index, 29, 20,
 277                        SJA1105ET_SIZE_L2_LOOKUP_ENTRY, op);
 278}
 279
 280static size_t sja1105et_dyn_l2_lookup_entry_packing(void *buf, void *entry_ptr,
 281                                                    enum packing_op op)
 282{
 283        struct sja1105_l2_lookup_entry *entry = entry_ptr;
 284        u8 *cmd = buf + SJA1105ET_SIZE_L2_LOOKUP_ENTRY;
 285        const int size = SJA1105_SIZE_DYN_CMD;
 286
 287        sja1105_packing(cmd, &entry->lockeds, 28, 28, size, op);
 288
 289        return sja1105et_l2_lookup_entry_packing(buf, entry_ptr, op);
 290}
 291
 292static void
 293sja1105et_mgmt_route_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
 294                                 enum packing_op op)
 295{
 296        u8 *p = buf + SJA1105ET_SIZE_L2_LOOKUP_ENTRY;
 297        u64 mgmtroute = 1;
 298
 299        sja1105et_l2_lookup_cmd_packing(buf, cmd, op);
 300        if (op == PACK)
 301                sja1105_pack(p, &mgmtroute, 26, 26, SJA1105_SIZE_DYN_CMD);
 302}
 303
 304static size_t sja1105et_mgmt_route_entry_packing(void *buf, void *entry_ptr,
 305                                                 enum packing_op op)
 306{
 307        struct sja1105_mgmt_entry *entry = entry_ptr;
 308        const size_t size = SJA1105ET_SIZE_L2_LOOKUP_ENTRY;
 309
 310        /* UM10944: To specify if a PTP egress timestamp shall be captured on
 311         * each port upon transmission of the frame, the LSB of VLANID in the
 312         * ENTRY field provided by the host must be set.
 313         * Bit 1 of VLANID then specifies the register where the timestamp for
 314         * this port is stored in.
 315         */
 316        sja1105_packing(buf, &entry->tsreg,     85, 85, size, op);
 317        sja1105_packing(buf, &entry->takets,    84, 84, size, op);
 318        sja1105_packing(buf, &entry->macaddr,   83, 36, size, op);
 319        sja1105_packing(buf, &entry->destports, 35, 31, size, op);
 320        sja1105_packing(buf, &entry->enfport,   30, 30, size, op);
 321        return size;
 322}
 323
 324static void
 325sja1105pqrs_mgmt_route_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
 326                                   enum packing_op op)
 327{
 328        u8 *p = buf + SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY;
 329        u64 mgmtroute = 1;
 330
 331        sja1105pqrs_l2_lookup_cmd_packing(buf, cmd, op);
 332        if (op == PACK)
 333                sja1105_pack(p, &mgmtroute, 26, 26, SJA1105_SIZE_DYN_CMD);
 334}
 335
 336static size_t sja1105pqrs_mgmt_route_entry_packing(void *buf, void *entry_ptr,
 337                                                   enum packing_op op)
 338{
 339        const size_t size = SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY;
 340        struct sja1105_mgmt_entry *entry = entry_ptr;
 341
 342        /* In P/Q/R/S, enfport got renamed to mgmtvalid, but its purpose
 343         * is the same (driver uses it to confirm that frame was sent).
 344         * So just keep the name from E/T.
 345         */
 346        sja1105_packing(buf, &entry->tsreg,     71, 71, size, op);
 347        sja1105_packing(buf, &entry->takets,    70, 70, size, op);
 348        sja1105_packing(buf, &entry->macaddr,   69, 22, size, op);
 349        sja1105_packing(buf, &entry->destports, 21, 17, size, op);
 350        sja1105_packing(buf, &entry->enfport,   16, 16, size, op);
 351        return size;
 352}
 353
 354/* In E/T, entry is at addresses 0x27-0x28. There is a 4 byte gap at 0x29,
 355 * and command is at 0x2a. Similarly in P/Q/R/S there is a 1 register gap
 356 * between entry (0x2d, 0x2e) and command (0x30).
 357 */
 358static void
 359sja1105_vlan_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
 360                                enum packing_op op)
 361{
 362        u8 *p = buf + SJA1105_SIZE_VLAN_LOOKUP_ENTRY + 4;
 363        const int size = SJA1105_SIZE_DYN_CMD;
 364
 365        sja1105_packing(p, &cmd->valid,    31, 31, size, op);
 366        sja1105_packing(p, &cmd->rdwrset,  30, 30, size, op);
 367        sja1105_packing(p, &cmd->valident, 27, 27, size, op);
 368        /* Hack - see comments above, applied for 'vlanid' field of
 369         * struct sja1105_vlan_lookup_entry.
 370         */
 371        sja1105_packing(buf, &cmd->index, 38, 27,
 372                        SJA1105_SIZE_VLAN_LOOKUP_ENTRY, op);
 373}
 374
 375static void
 376sja1105_l2_forwarding_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
 377                                  enum packing_op op)
 378{
 379        u8 *p = buf + SJA1105_SIZE_L2_FORWARDING_ENTRY;
 380        const int size = SJA1105_SIZE_DYN_CMD;
 381
 382        sja1105_packing(p, &cmd->valid,   31, 31, size, op);
 383        sja1105_packing(p, &cmd->errors,  30, 30, size, op);
 384        sja1105_packing(p, &cmd->rdwrset, 29, 29, size, op);
 385        sja1105_packing(p, &cmd->index,    4,  0, size, op);
 386}
 387
 388static void
 389sja1105et_mac_config_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
 390                                 enum packing_op op)
 391{
 392        const int size = SJA1105_SIZE_DYN_CMD;
 393        /* Yup, user manual definitions are reversed */
 394        u8 *reg1 = buf + 4;
 395
 396        sja1105_packing(reg1, &cmd->valid, 31, 31, size, op);
 397        sja1105_packing(reg1, &cmd->index, 26, 24, size, op);
 398}
 399
 400static size_t sja1105et_mac_config_entry_packing(void *buf, void *entry_ptr,
 401                                                 enum packing_op op)
 402{
 403        const int size = SJA1105ET_SIZE_MAC_CONFIG_DYN_ENTRY;
 404        struct sja1105_mac_config_entry *entry = entry_ptr;
 405        /* Yup, user manual definitions are reversed */
 406        u8 *reg1 = buf + 4;
 407        u8 *reg2 = buf;
 408
 409        sja1105_packing(reg1, &entry->speed,     30, 29, size, op);
 410        sja1105_packing(reg1, &entry->drpdtag,   23, 23, size, op);
 411        sja1105_packing(reg1, &entry->drpuntag,  22, 22, size, op);
 412        sja1105_packing(reg1, &entry->retag,     21, 21, size, op);
 413        sja1105_packing(reg1, &entry->dyn_learn, 20, 20, size, op);
 414        sja1105_packing(reg1, &entry->egress,    19, 19, size, op);
 415        sja1105_packing(reg1, &entry->ingress,   18, 18, size, op);
 416        sja1105_packing(reg1, &entry->ing_mirr,  17, 17, size, op);
 417        sja1105_packing(reg1, &entry->egr_mirr,  16, 16, size, op);
 418        sja1105_packing(reg1, &entry->vlanprio,  14, 12, size, op);
 419        sja1105_packing(reg1, &entry->vlanid,    11,  0, size, op);
 420        sja1105_packing(reg2, &entry->tp_delin,  31, 16, size, op);
 421        sja1105_packing(reg2, &entry->tp_delout, 15,  0, size, op);
 422        /* MAC configuration table entries which can't be reconfigured:
 423         * top, base, enabled, ifg, maxage, drpnona664
 424         */
 425        /* Bogus return value, not used anywhere */
 426        return 0;
 427}
 428
 429static void
 430sja1105pqrs_mac_config_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
 431                                   enum packing_op op)
 432{
 433        const int size = SJA1105ET_SIZE_MAC_CONFIG_DYN_ENTRY;
 434        u8 *p = buf + SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY;
 435
 436        sja1105_packing(p, &cmd->valid,   31, 31, size, op);
 437        sja1105_packing(p, &cmd->errors,  30, 30, size, op);
 438        sja1105_packing(p, &cmd->rdwrset, 29, 29, size, op);
 439        sja1105_packing(p, &cmd->index,    2,  0, size, op);
 440}
 441
 442static void
 443sja1105et_l2_lookup_params_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
 444                                       enum packing_op op)
 445{
 446        sja1105_packing(buf, &cmd->valid, 31, 31,
 447                        SJA1105ET_SIZE_L2_LOOKUP_PARAMS_DYN_CMD, op);
 448}
 449
 450static size_t
 451sja1105et_l2_lookup_params_entry_packing(void *buf, void *entry_ptr,
 452                                         enum packing_op op)
 453{
 454        struct sja1105_l2_lookup_params_entry *entry = entry_ptr;
 455
 456        sja1105_packing(buf, &entry->poly, 7, 0,
 457                        SJA1105ET_SIZE_L2_LOOKUP_PARAMS_DYN_CMD, op);
 458        /* Bogus return value, not used anywhere */
 459        return 0;
 460}
 461
 462static void
 463sja1105et_general_params_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
 464                                     enum packing_op op)
 465{
 466        const int size = SJA1105ET_SIZE_GENERAL_PARAMS_DYN_CMD;
 467
 468        sja1105_packing(buf, &cmd->valid,  31, 31, size, op);
 469        sja1105_packing(buf, &cmd->errors, 30, 30, size, op);
 470}
 471
 472static size_t
 473sja1105et_general_params_entry_packing(void *buf, void *entry_ptr,
 474                                       enum packing_op op)
 475{
 476        struct sja1105_general_params_entry *entry = entry_ptr;
 477        const int size = SJA1105ET_SIZE_GENERAL_PARAMS_DYN_CMD;
 478
 479        sja1105_packing(buf, &entry->mirr_port, 2, 0, size, op);
 480        /* Bogus return value, not used anywhere */
 481        return 0;
 482}
 483
 484#define OP_READ         BIT(0)
 485#define OP_WRITE        BIT(1)
 486#define OP_DEL          BIT(2)
 487#define OP_SEARCH       BIT(3)
 488
 489/* SJA1105E/T: First generation */
 490struct sja1105_dynamic_table_ops sja1105et_dyn_ops[BLK_IDX_MAX_DYN] = {
 491        [BLK_IDX_L2_LOOKUP] = {
 492                .entry_packing = sja1105et_dyn_l2_lookup_entry_packing,
 493                .cmd_packing = sja1105et_l2_lookup_cmd_packing,
 494                .access = (OP_READ | OP_WRITE | OP_DEL),
 495                .max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT,
 496                .packed_size = SJA1105ET_SIZE_L2_LOOKUP_DYN_CMD,
 497                .addr = 0x20,
 498        },
 499        [BLK_IDX_MGMT_ROUTE] = {
 500                .entry_packing = sja1105et_mgmt_route_entry_packing,
 501                .cmd_packing = sja1105et_mgmt_route_cmd_packing,
 502                .access = (OP_READ | OP_WRITE),
 503                .max_entry_count = SJA1105_NUM_PORTS,
 504                .packed_size = SJA1105ET_SIZE_L2_LOOKUP_DYN_CMD,
 505                .addr = 0x20,
 506        },
 507        [BLK_IDX_L2_POLICING] = {0},
 508        [BLK_IDX_VLAN_LOOKUP] = {
 509                .entry_packing = sja1105_vlan_lookup_entry_packing,
 510                .cmd_packing = sja1105_vlan_lookup_cmd_packing,
 511                .access = (OP_WRITE | OP_DEL),
 512                .max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT,
 513                .packed_size = SJA1105_SIZE_VLAN_LOOKUP_DYN_CMD,
 514                .addr = 0x27,
 515        },
 516        [BLK_IDX_L2_FORWARDING] = {
 517                .entry_packing = sja1105_l2_forwarding_entry_packing,
 518                .cmd_packing = sja1105_l2_forwarding_cmd_packing,
 519                .max_entry_count = SJA1105_MAX_L2_FORWARDING_COUNT,
 520                .access = OP_WRITE,
 521                .packed_size = SJA1105_SIZE_L2_FORWARDING_DYN_CMD,
 522                .addr = 0x24,
 523        },
 524        [BLK_IDX_MAC_CONFIG] = {
 525                .entry_packing = sja1105et_mac_config_entry_packing,
 526                .cmd_packing = sja1105et_mac_config_cmd_packing,
 527                .max_entry_count = SJA1105_MAX_MAC_CONFIG_COUNT,
 528                .access = OP_WRITE,
 529                .packed_size = SJA1105ET_SIZE_MAC_CONFIG_DYN_CMD,
 530                .addr = 0x36,
 531        },
 532        [BLK_IDX_L2_LOOKUP_PARAMS] = {
 533                .entry_packing = sja1105et_l2_lookup_params_entry_packing,
 534                .cmd_packing = sja1105et_l2_lookup_params_cmd_packing,
 535                .max_entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT,
 536                .access = OP_WRITE,
 537                .packed_size = SJA1105ET_SIZE_L2_LOOKUP_PARAMS_DYN_CMD,
 538                .addr = 0x38,
 539        },
 540        [BLK_IDX_L2_FORWARDING_PARAMS] = {0},
 541        [BLK_IDX_AVB_PARAMS] = {0},
 542        [BLK_IDX_GENERAL_PARAMS] = {
 543                .entry_packing = sja1105et_general_params_entry_packing,
 544                .cmd_packing = sja1105et_general_params_cmd_packing,
 545                .max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT,
 546                .access = OP_WRITE,
 547                .packed_size = SJA1105ET_SIZE_GENERAL_PARAMS_DYN_CMD,
 548                .addr = 0x34,
 549        },
 550        [BLK_IDX_XMII_PARAMS] = {0},
 551};
 552
 553/* SJA1105P/Q/R/S: Second generation */
 554struct sja1105_dynamic_table_ops sja1105pqrs_dyn_ops[BLK_IDX_MAX_DYN] = {
 555        [BLK_IDX_L2_LOOKUP] = {
 556                .entry_packing = sja1105pqrs_dyn_l2_lookup_entry_packing,
 557                .cmd_packing = sja1105pqrs_l2_lookup_cmd_packing,
 558                .access = (OP_READ | OP_WRITE | OP_DEL | OP_SEARCH),
 559                .max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT,
 560                .packed_size = SJA1105PQRS_SIZE_L2_LOOKUP_DYN_CMD,
 561                .addr = 0x24,
 562        },
 563        [BLK_IDX_MGMT_ROUTE] = {
 564                .entry_packing = sja1105pqrs_mgmt_route_entry_packing,
 565                .cmd_packing = sja1105pqrs_mgmt_route_cmd_packing,
 566                .access = (OP_READ | OP_WRITE | OP_DEL | OP_SEARCH),
 567                .max_entry_count = SJA1105_NUM_PORTS,
 568                .packed_size = SJA1105PQRS_SIZE_L2_LOOKUP_DYN_CMD,
 569                .addr = 0x24,
 570        },
 571        [BLK_IDX_L2_POLICING] = {0},
 572        [BLK_IDX_VLAN_LOOKUP] = {
 573                .entry_packing = sja1105_vlan_lookup_entry_packing,
 574                .cmd_packing = sja1105_vlan_lookup_cmd_packing,
 575                .access = (OP_READ | OP_WRITE | OP_DEL),
 576                .max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT,
 577                .packed_size = SJA1105_SIZE_VLAN_LOOKUP_DYN_CMD,
 578                .addr = 0x2D,
 579        },
 580        [BLK_IDX_L2_FORWARDING] = {
 581                .entry_packing = sja1105_l2_forwarding_entry_packing,
 582                .cmd_packing = sja1105_l2_forwarding_cmd_packing,
 583                .max_entry_count = SJA1105_MAX_L2_FORWARDING_COUNT,
 584                .access = OP_WRITE,
 585                .packed_size = SJA1105_SIZE_L2_FORWARDING_DYN_CMD,
 586                .addr = 0x2A,
 587        },
 588        [BLK_IDX_MAC_CONFIG] = {
 589                .entry_packing = sja1105pqrs_mac_config_entry_packing,
 590                .cmd_packing = sja1105pqrs_mac_config_cmd_packing,
 591                .max_entry_count = SJA1105_MAX_MAC_CONFIG_COUNT,
 592                .access = (OP_READ | OP_WRITE),
 593                .packed_size = SJA1105PQRS_SIZE_MAC_CONFIG_DYN_CMD,
 594                .addr = 0x4B,
 595        },
 596        [BLK_IDX_L2_LOOKUP_PARAMS] = {
 597                .entry_packing = sja1105et_l2_lookup_params_entry_packing,
 598                .cmd_packing = sja1105et_l2_lookup_params_cmd_packing,
 599                .max_entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT,
 600                .access = (OP_READ | OP_WRITE),
 601                .packed_size = SJA1105ET_SIZE_L2_LOOKUP_PARAMS_DYN_CMD,
 602                .addr = 0x38,
 603        },
 604        [BLK_IDX_L2_FORWARDING_PARAMS] = {0},
 605        [BLK_IDX_AVB_PARAMS] = {0},
 606        [BLK_IDX_GENERAL_PARAMS] = {
 607                .entry_packing = sja1105et_general_params_entry_packing,
 608                .cmd_packing = sja1105et_general_params_cmd_packing,
 609                .max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT,
 610                .access = OP_WRITE,
 611                .packed_size = SJA1105ET_SIZE_GENERAL_PARAMS_DYN_CMD,
 612                .addr = 0x34,
 613        },
 614        [BLK_IDX_XMII_PARAMS] = {0},
 615};
 616
 617/* Provides read access to the settings through the dynamic interface
 618 * of the switch.
 619 * @blk_idx     is used as key to select from the sja1105_dynamic_table_ops.
 620 *              The selection is limited by the hardware in respect to which
 621 *              configuration blocks can be read through the dynamic interface.
 622 * @index       is used to retrieve a particular table entry. If negative,
 623 *              (and if the @blk_idx supports the searching operation) a search
 624 *              is performed by the @entry parameter.
 625 * @entry       Type-casted to an unpacked structure that holds a table entry
 626 *              of the type specified in @blk_idx.
 627 *              Usually an output argument. If @index is negative, then this
 628 *              argument is used as input/output: it should be pre-populated
 629 *              with the element to search for. Entries which support the
 630 *              search operation will have an "index" field (not the @index
 631 *              argument to this function) and that is where the found index
 632 *              will be returned (or left unmodified - thus negative - if not
 633 *              found).
 634 */
 635int sja1105_dynamic_config_read(struct sja1105_private *priv,
 636                                enum sja1105_blk_idx blk_idx,
 637                                int index, void *entry)
 638{
 639        const struct sja1105_dynamic_table_ops *ops;
 640        struct sja1105_dyn_cmd cmd = {0};
 641        /* SPI payload buffer */
 642        u8 packed_buf[SJA1105_MAX_DYN_CMD_SIZE] = {0};
 643        int retries = 3;
 644        int rc;
 645
 646        if (blk_idx >= BLK_IDX_MAX_DYN)
 647                return -ERANGE;
 648
 649        ops = &priv->info->dyn_ops[blk_idx];
 650
 651        if (index >= 0 && index >= ops->max_entry_count)
 652                return -ERANGE;
 653        if (index < 0 && !(ops->access & OP_SEARCH))
 654                return -EOPNOTSUPP;
 655        if (!(ops->access & OP_READ))
 656                return -EOPNOTSUPP;
 657        if (ops->packed_size > SJA1105_MAX_DYN_CMD_SIZE)
 658                return -ERANGE;
 659        if (!ops->cmd_packing)
 660                return -EOPNOTSUPP;
 661        if (!ops->entry_packing)
 662                return -EOPNOTSUPP;
 663
 664        cmd.valid = true; /* Trigger action on table entry */
 665        cmd.rdwrset = SPI_READ; /* Action is read */
 666        if (index < 0) {
 667                /* Avoid copying a signed negative number to an u64 */
 668                cmd.index = 0;
 669                cmd.search = true;
 670        } else {
 671                cmd.index = index;
 672                cmd.search = false;
 673        }
 674        cmd.valident = true;
 675        ops->cmd_packing(packed_buf, &cmd, PACK);
 676
 677        if (cmd.search)
 678                ops->entry_packing(packed_buf, entry, PACK);
 679
 680        /* Send SPI write operation: read config table entry */
 681        rc = sja1105_spi_send_packed_buf(priv, SPI_WRITE, ops->addr,
 682                                         packed_buf, ops->packed_size);
 683        if (rc < 0)
 684                return rc;
 685
 686        /* Loop until we have confirmation that hardware has finished
 687         * processing the command and has cleared the VALID field
 688         */
 689        do {
 690                memset(packed_buf, 0, ops->packed_size);
 691
 692                /* Retrieve the read operation's result */
 693                rc = sja1105_spi_send_packed_buf(priv, SPI_READ, ops->addr,
 694                                                 packed_buf, ops->packed_size);
 695                if (rc < 0)
 696                        return rc;
 697
 698                cmd = (struct sja1105_dyn_cmd) {0};
 699                ops->cmd_packing(packed_buf, &cmd, UNPACK);
 700                /* UM10944: [valident] will always be found cleared
 701                 * during a read access with MGMTROUTE set.
 702                 * So don't error out in that case.
 703                 */
 704                if (!cmd.valident && blk_idx != BLK_IDX_MGMT_ROUTE)
 705                        return -ENOENT;
 706                cpu_relax();
 707        } while (cmd.valid && --retries);
 708
 709        if (cmd.valid)
 710                return -ETIMEDOUT;
 711
 712        /* Don't dereference possibly NULL pointer - maybe caller
 713         * only wanted to see whether the entry existed or not.
 714         */
 715        if (entry)
 716                ops->entry_packing(packed_buf, entry, UNPACK);
 717        return 0;
 718}
 719
 720int sja1105_dynamic_config_write(struct sja1105_private *priv,
 721                                 enum sja1105_blk_idx blk_idx,
 722                                 int index, void *entry, bool keep)
 723{
 724        const struct sja1105_dynamic_table_ops *ops;
 725        struct sja1105_dyn_cmd cmd = {0};
 726        /* SPI payload buffer */
 727        u8 packed_buf[SJA1105_MAX_DYN_CMD_SIZE] = {0};
 728        int rc;
 729
 730        if (blk_idx >= BLK_IDX_MAX_DYN)
 731                return -ERANGE;
 732
 733        ops = &priv->info->dyn_ops[blk_idx];
 734
 735        if (index >= ops->max_entry_count)
 736                return -ERANGE;
 737        if (index < 0)
 738                return -ERANGE;
 739        if (!(ops->access & OP_WRITE))
 740                return -EOPNOTSUPP;
 741        if (!keep && !(ops->access & OP_DEL))
 742                return -EOPNOTSUPP;
 743        if (ops->packed_size > SJA1105_MAX_DYN_CMD_SIZE)
 744                return -ERANGE;
 745
 746        cmd.valident = keep; /* If false, deletes entry */
 747        cmd.valid = true; /* Trigger action on table entry */
 748        cmd.rdwrset = SPI_WRITE; /* Action is write */
 749        cmd.index = index;
 750
 751        if (!ops->cmd_packing)
 752                return -EOPNOTSUPP;
 753        ops->cmd_packing(packed_buf, &cmd, PACK);
 754
 755        if (!ops->entry_packing)
 756                return -EOPNOTSUPP;
 757        /* Don't dereference potentially NULL pointer if just
 758         * deleting a table entry is what was requested. For cases
 759         * where 'index' field is physically part of entry structure,
 760         * and needed here, we deal with that in the cmd_packing callback.
 761         */
 762        if (keep)
 763                ops->entry_packing(packed_buf, entry, PACK);
 764
 765        /* Send SPI write operation: read config table entry */
 766        rc = sja1105_spi_send_packed_buf(priv, SPI_WRITE, ops->addr,
 767                                         packed_buf, ops->packed_size);
 768        if (rc < 0)
 769                return rc;
 770
 771        cmd = (struct sja1105_dyn_cmd) {0};
 772        ops->cmd_packing(packed_buf, &cmd, UNPACK);
 773        if (cmd.errors)
 774                return -EINVAL;
 775
 776        return 0;
 777}
 778
 779static u8 sja1105_crc8_add(u8 crc, u8 byte, u8 poly)
 780{
 781        int i;
 782
 783        for (i = 0; i < 8; i++) {
 784                if ((crc ^ byte) & (1 << 7)) {
 785                        crc <<= 1;
 786                        crc ^= poly;
 787                } else {
 788                        crc <<= 1;
 789                }
 790                byte <<= 1;
 791        }
 792        return crc;
 793}
 794
 795/* CRC8 algorithm with non-reversed input, non-reversed output,
 796 * no input xor and no output xor. Code customized for receiving
 797 * the SJA1105 E/T FDB keys (vlanid, macaddr) as input. CRC polynomial
 798 * is also received as argument in the Koopman notation that the switch
 799 * hardware stores it in.
 800 */
 801u8 sja1105et_fdb_hash(struct sja1105_private *priv, const u8 *addr, u16 vid)
 802{
 803        struct sja1105_l2_lookup_params_entry *l2_lookup_params =
 804                priv->static_config.tables[BLK_IDX_L2_LOOKUP_PARAMS].entries;
 805        u64 poly_koopman = l2_lookup_params->poly;
 806        /* Convert polynomial from Koopman to 'normal' notation */
 807        u8 poly = (u8)(1 + (poly_koopman << 1));
 808        u64 vlanid = l2_lookup_params->shared_learn ? 0 : vid;
 809        u64 input = (vlanid << 48) | ether_addr_to_u64(addr);
 810        u8 crc = 0; /* seed */
 811        int i;
 812
 813        /* Mask the eight bytes starting from MSB one at a time */
 814        for (i = 56; i >= 0; i -= 8) {
 815                u8 byte = (input & (0xffull << i)) >> i;
 816
 817                crc = sja1105_crc8_add(crc, byte, poly);
 818        }
 819        return crc;
 820}
 821