linux/drivers/net/ethernet/chelsio/cxgb3/mc5.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2003-2008 Chelsio, Inc. All rights reserved.
   3 *
   4 * This software is available to you under a choice of one of two
   5 * licenses.  You may choose to be licensed under the terms of the GNU
   6 * General Public License (GPL) Version 2, available from the file
   7 * COPYING in the main directory of this source tree, or the
   8 * OpenIB.org BSD license below:
   9 *
  10 *     Redistribution and use in source and binary forms, with or
  11 *     without modification, are permitted provided that the following
  12 *     conditions are met:
  13 *
  14 *      - Redistributions of source code must retain the above
  15 *        copyright notice, this list of conditions and the following
  16 *        disclaimer.
  17 *
  18 *      - Redistributions in binary form must reproduce the above
  19 *        copyright notice, this list of conditions and the following
  20 *        disclaimer in the documentation and/or other materials
  21 *        provided with the distribution.
  22 *
  23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  30 * SOFTWARE.
  31 */
  32#include "common.h"
  33#include "regs.h"
  34
  35enum {
  36        IDT75P52100 = 4,
  37        IDT75N43102 = 5
  38};
  39
  40/* DBGI command mode */
  41enum {
  42        DBGI_MODE_MBUS = 0,
  43        DBGI_MODE_IDT52100 = 5
  44};
  45
  46/* IDT 75P52100 commands */
  47#define IDT_CMD_READ   0
  48#define IDT_CMD_WRITE  1
  49#define IDT_CMD_SEARCH 2
  50#define IDT_CMD_LEARN  3
  51
  52/* IDT LAR register address and value for 144-bit mode (low 32 bits) */
  53#define IDT_LAR_ADR0    0x180006
  54#define IDT_LAR_MODE144 0xffff0000
  55
  56/* IDT SCR and SSR addresses (low 32 bits) */
  57#define IDT_SCR_ADR0  0x180000
  58#define IDT_SSR0_ADR0 0x180002
  59#define IDT_SSR1_ADR0 0x180004
  60
  61/* IDT GMR base address (low 32 bits) */
  62#define IDT_GMR_BASE_ADR0 0x180020
  63
  64/* IDT data and mask array base addresses (low 32 bits) */
  65#define IDT_DATARY_BASE_ADR0 0
  66#define IDT_MSKARY_BASE_ADR0 0x80000
  67
  68/* IDT 75N43102 commands */
  69#define IDT4_CMD_SEARCH144 3
  70#define IDT4_CMD_WRITE     4
  71#define IDT4_CMD_READ      5
  72
  73/* IDT 75N43102 SCR address (low 32 bits) */
  74#define IDT4_SCR_ADR0  0x3
  75
  76/* IDT 75N43102 GMR base addresses (low 32 bits) */
  77#define IDT4_GMR_BASE0 0x10
  78#define IDT4_GMR_BASE1 0x20
  79#define IDT4_GMR_BASE2 0x30
  80
  81/* IDT 75N43102 data and mask array base addresses (low 32 bits) */
  82#define IDT4_DATARY_BASE_ADR0 0x1000000
  83#define IDT4_MSKARY_BASE_ADR0 0x2000000
  84
  85#define MAX_WRITE_ATTEMPTS 5
  86
  87#define MAX_ROUTES 2048
  88
  89/*
  90 * Issue a command to the TCAM and wait for its completion.  The address and
  91 * any data required by the command must have been setup by the caller.
  92 */
  93static int mc5_cmd_write(struct adapter *adapter, u32 cmd)
  94{
  95        t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_CMD, cmd);
  96        return t3_wait_op_done(adapter, A_MC5_DB_DBGI_RSP_STATUS,
  97                               F_DBGIRSPVALID, 1, MAX_WRITE_ATTEMPTS, 1);
  98}
  99
 100static inline void dbgi_wr_data3(struct adapter *adapter, u32 v1, u32 v2,
 101                                 u32 v3)
 102{
 103        t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_DATA0, v1);
 104        t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_DATA1, v2);
 105        t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_DATA2, v3);
 106}
 107
 108/*
 109 * Write data to the TCAM register at address (0, 0, addr_lo) using the TCAM
 110 * command cmd.  The data to be written must have been set up by the caller.
 111 * Returns -1 on failure, 0 on success.
 112 */
 113static int mc5_write(struct adapter *adapter, u32 addr_lo, u32 cmd)
 114{
 115        t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_ADDR0, addr_lo);
 116        if (mc5_cmd_write(adapter, cmd) == 0)
 117                return 0;
 118        CH_ERR(adapter, "MC5 timeout writing to TCAM address 0x%x\n",
 119               addr_lo);
 120        return -1;
 121}
 122
 123static int init_mask_data_array(struct mc5 *mc5, u32 mask_array_base,
 124                                u32 data_array_base, u32 write_cmd,
 125                                int addr_shift)
 126{
 127        unsigned int i;
 128        struct adapter *adap = mc5->adapter;
 129
 130        /*
 131         * We need the size of the TCAM data and mask arrays in terms of
 132         * 72-bit entries.
 133         */
 134        unsigned int size72 = mc5->tcam_size;
 135        unsigned int server_base = t3_read_reg(adap, A_MC5_DB_SERVER_INDEX);
 136
 137        if (mc5->mode == MC5_MODE_144_BIT) {
 138                size72 *= 2;    /* 1 144-bit entry is 2 72-bit entries */
 139                server_base *= 2;
 140        }
 141
 142        /* Clear the data array */
 143        dbgi_wr_data3(adap, 0, 0, 0);
 144        for (i = 0; i < size72; i++)
 145                if (mc5_write(adap, data_array_base + (i << addr_shift),
 146                              write_cmd))
 147                        return -1;
 148
 149        /* Initialize the mask array. */
 150        dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0xff);
 151        for (i = 0; i < size72; i++) {
 152                if (i == server_base)   /* entering server or routing region */
 153                        t3_write_reg(adap, A_MC5_DB_DBGI_REQ_DATA0,
 154                                     mc5->mode == MC5_MODE_144_BIT ?
 155                                     0xfffffff9 : 0xfffffffd);
 156                if (mc5_write(adap, mask_array_base + (i << addr_shift),
 157                              write_cmd))
 158                        return -1;
 159        }
 160        return 0;
 161}
 162
 163static int init_idt52100(struct mc5 *mc5)
 164{
 165        int i;
 166        struct adapter *adap = mc5->adapter;
 167
 168        t3_write_reg(adap, A_MC5_DB_RSP_LATENCY,
 169                     V_RDLAT(0x15) | V_LRNLAT(0x15) | V_SRCHLAT(0x15));
 170        t3_write_reg(adap, A_MC5_DB_PART_ID_INDEX, 2);
 171
 172        /*
 173         * Use GMRs 14-15 for ELOOKUP, GMRs 12-13 for SYN lookups, and
 174         * GMRs 8-9 for ACK- and AOPEN searches.
 175         */
 176        t3_write_reg(adap, A_MC5_DB_POPEN_DATA_WR_CMD, IDT_CMD_WRITE);
 177        t3_write_reg(adap, A_MC5_DB_POPEN_MASK_WR_CMD, IDT_CMD_WRITE);
 178        t3_write_reg(adap, A_MC5_DB_AOPEN_SRCH_CMD, IDT_CMD_SEARCH);
 179        t3_write_reg(adap, A_MC5_DB_AOPEN_LRN_CMD, IDT_CMD_LEARN);
 180        t3_write_reg(adap, A_MC5_DB_SYN_SRCH_CMD, IDT_CMD_SEARCH | 0x6000);
 181        t3_write_reg(adap, A_MC5_DB_SYN_LRN_CMD, IDT_CMD_LEARN);
 182        t3_write_reg(adap, A_MC5_DB_ACK_SRCH_CMD, IDT_CMD_SEARCH);
 183        t3_write_reg(adap, A_MC5_DB_ACK_LRN_CMD, IDT_CMD_LEARN);
 184        t3_write_reg(adap, A_MC5_DB_ILOOKUP_CMD, IDT_CMD_SEARCH);
 185        t3_write_reg(adap, A_MC5_DB_ELOOKUP_CMD, IDT_CMD_SEARCH | 0x7000);
 186        t3_write_reg(adap, A_MC5_DB_DATA_WRITE_CMD, IDT_CMD_WRITE);
 187        t3_write_reg(adap, A_MC5_DB_DATA_READ_CMD, IDT_CMD_READ);
 188
 189        /* Set DBGI command mode for IDT TCAM. */
 190        t3_write_reg(adap, A_MC5_DB_DBGI_CONFIG, DBGI_MODE_IDT52100);
 191
 192        /* Set up LAR */
 193        dbgi_wr_data3(adap, IDT_LAR_MODE144, 0, 0);
 194        if (mc5_write(adap, IDT_LAR_ADR0, IDT_CMD_WRITE))
 195                goto err;
 196
 197        /* Set up SSRs */
 198        dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0);
 199        if (mc5_write(adap, IDT_SSR0_ADR0, IDT_CMD_WRITE) ||
 200            mc5_write(adap, IDT_SSR1_ADR0, IDT_CMD_WRITE))
 201                goto err;
 202
 203        /* Set up GMRs */
 204        for (i = 0; i < 32; ++i) {
 205                if (i >= 12 && i < 15)
 206                        dbgi_wr_data3(adap, 0xfffffff9, 0xffffffff, 0xff);
 207                else if (i == 15)
 208                        dbgi_wr_data3(adap, 0xfffffff9, 0xffff8007, 0xff);
 209                else
 210                        dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0xff);
 211
 212                if (mc5_write(adap, IDT_GMR_BASE_ADR0 + i, IDT_CMD_WRITE))
 213                        goto err;
 214        }
 215
 216        /* Set up SCR */
 217        dbgi_wr_data3(adap, 1, 0, 0);
 218        if (mc5_write(adap, IDT_SCR_ADR0, IDT_CMD_WRITE))
 219                goto err;
 220
 221        return init_mask_data_array(mc5, IDT_MSKARY_BASE_ADR0,
 222                                    IDT_DATARY_BASE_ADR0, IDT_CMD_WRITE, 0);
 223err:
 224        return -EIO;
 225}
 226
 227static int init_idt43102(struct mc5 *mc5)
 228{
 229        int i;
 230        struct adapter *adap = mc5->adapter;
 231
 232        t3_write_reg(adap, A_MC5_DB_RSP_LATENCY,
 233                     adap->params.rev == 0 ? V_RDLAT(0xd) | V_SRCHLAT(0x11) :
 234                     V_RDLAT(0xd) | V_SRCHLAT(0x12));
 235
 236        /*
 237         * Use GMRs 24-25 for ELOOKUP, GMRs 20-21 for SYN lookups, and no mask
 238         * for ACK- and AOPEN searches.
 239         */
 240        t3_write_reg(adap, A_MC5_DB_POPEN_DATA_WR_CMD, IDT4_CMD_WRITE);
 241        t3_write_reg(adap, A_MC5_DB_POPEN_MASK_WR_CMD, IDT4_CMD_WRITE);
 242        t3_write_reg(adap, A_MC5_DB_AOPEN_SRCH_CMD,
 243                     IDT4_CMD_SEARCH144 | 0x3800);
 244        t3_write_reg(adap, A_MC5_DB_SYN_SRCH_CMD, IDT4_CMD_SEARCH144);
 245        t3_write_reg(adap, A_MC5_DB_ACK_SRCH_CMD, IDT4_CMD_SEARCH144 | 0x3800);
 246        t3_write_reg(adap, A_MC5_DB_ILOOKUP_CMD, IDT4_CMD_SEARCH144 | 0x3800);
 247        t3_write_reg(adap, A_MC5_DB_ELOOKUP_CMD, IDT4_CMD_SEARCH144 | 0x800);
 248        t3_write_reg(adap, A_MC5_DB_DATA_WRITE_CMD, IDT4_CMD_WRITE);
 249        t3_write_reg(adap, A_MC5_DB_DATA_READ_CMD, IDT4_CMD_READ);
 250
 251        t3_write_reg(adap, A_MC5_DB_PART_ID_INDEX, 3);
 252
 253        /* Set DBGI command mode for IDT TCAM. */
 254        t3_write_reg(adap, A_MC5_DB_DBGI_CONFIG, DBGI_MODE_IDT52100);
 255
 256        /* Set up GMRs */
 257        dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0xff);
 258        for (i = 0; i < 7; ++i)
 259                if (mc5_write(adap, IDT4_GMR_BASE0 + i, IDT4_CMD_WRITE))
 260                        goto err;
 261
 262        for (i = 0; i < 4; ++i)
 263                if (mc5_write(adap, IDT4_GMR_BASE2 + i, IDT4_CMD_WRITE))
 264                        goto err;
 265
 266        dbgi_wr_data3(adap, 0xfffffff9, 0xffffffff, 0xff);
 267        if (mc5_write(adap, IDT4_GMR_BASE1, IDT4_CMD_WRITE) ||
 268            mc5_write(adap, IDT4_GMR_BASE1 + 1, IDT4_CMD_WRITE) ||
 269            mc5_write(adap, IDT4_GMR_BASE1 + 4, IDT4_CMD_WRITE))
 270                goto err;
 271
 272        dbgi_wr_data3(adap, 0xfffffff9, 0xffff8007, 0xff);
 273        if (mc5_write(adap, IDT4_GMR_BASE1 + 5, IDT4_CMD_WRITE))
 274                goto err;
 275
 276        /* Set up SCR */
 277        dbgi_wr_data3(adap, 0xf0000000, 0, 0);
 278        if (mc5_write(adap, IDT4_SCR_ADR0, IDT4_CMD_WRITE))
 279                goto err;
 280
 281        return init_mask_data_array(mc5, IDT4_MSKARY_BASE_ADR0,
 282                                    IDT4_DATARY_BASE_ADR0, IDT4_CMD_WRITE, 1);
 283err:
 284        return -EIO;
 285}
 286
 287/* Put MC5 in DBGI mode. */
 288static inline void mc5_dbgi_mode_enable(const struct mc5 *mc5)
 289{
 290        t3_write_reg(mc5->adapter, A_MC5_DB_CONFIG,
 291                     V_TMMODE(mc5->mode == MC5_MODE_72_BIT) | F_DBGIEN);
 292}
 293
 294/* Put MC5 in M-Bus mode. */
 295static void mc5_dbgi_mode_disable(const struct mc5 *mc5)
 296{
 297        t3_write_reg(mc5->adapter, A_MC5_DB_CONFIG,
 298                     V_TMMODE(mc5->mode == MC5_MODE_72_BIT) |
 299                     V_COMPEN(mc5->mode == MC5_MODE_72_BIT) |
 300                     V_PRTYEN(mc5->parity_enabled) | F_MBUSEN);
 301}
 302
 303/*
 304 * Initialization that requires the OS and protocol layers to already
 305 * be initialized goes here.
 306 */
 307int t3_mc5_init(struct mc5 *mc5, unsigned int nservers, unsigned int nfilters,
 308                unsigned int nroutes)
 309{
 310        u32 cfg;
 311        int err;
 312        unsigned int tcam_size = mc5->tcam_size;
 313        struct adapter *adap = mc5->adapter;
 314
 315        if (!tcam_size)
 316                return 0;
 317
 318        if (nroutes > MAX_ROUTES || nroutes + nservers + nfilters > tcam_size)
 319                return -EINVAL;
 320
 321        /* Reset the TCAM */
 322        cfg = t3_read_reg(adap, A_MC5_DB_CONFIG) & ~F_TMMODE;
 323        cfg |= V_TMMODE(mc5->mode == MC5_MODE_72_BIT) | F_TMRST;
 324        t3_write_reg(adap, A_MC5_DB_CONFIG, cfg);
 325        if (t3_wait_op_done(adap, A_MC5_DB_CONFIG, F_TMRDY, 1, 500, 0)) {
 326                CH_ERR(adap, "TCAM reset timed out\n");
 327                return -1;
 328        }
 329
 330        t3_write_reg(adap, A_MC5_DB_ROUTING_TABLE_INDEX, tcam_size - nroutes);
 331        t3_write_reg(adap, A_MC5_DB_FILTER_TABLE,
 332                     tcam_size - nroutes - nfilters);
 333        t3_write_reg(adap, A_MC5_DB_SERVER_INDEX,
 334                     tcam_size - nroutes - nfilters - nservers);
 335
 336        mc5->parity_enabled = 1;
 337
 338        /* All the TCAM addresses we access have only the low 32 bits non 0 */
 339        t3_write_reg(adap, A_MC5_DB_DBGI_REQ_ADDR1, 0);
 340        t3_write_reg(adap, A_MC5_DB_DBGI_REQ_ADDR2, 0);
 341
 342        mc5_dbgi_mode_enable(mc5);
 343
 344        switch (mc5->part_type) {
 345        case IDT75P52100:
 346                err = init_idt52100(mc5);
 347                break;
 348        case IDT75N43102:
 349                err = init_idt43102(mc5);
 350                break;
 351        default:
 352                CH_ERR(adap, "Unsupported TCAM type %d\n", mc5->part_type);
 353                err = -EINVAL;
 354                break;
 355        }
 356
 357        mc5_dbgi_mode_disable(mc5);
 358        return err;
 359}
 360
 361
 362#define MC5_INT_FATAL (F_PARITYERR | F_REQQPARERR | F_DISPQPARERR)
 363
 364/*
 365 * MC5 interrupt handler
 366 */
 367void t3_mc5_intr_handler(struct mc5 *mc5)
 368{
 369        struct adapter *adap = mc5->adapter;
 370        u32 cause = t3_read_reg(adap, A_MC5_DB_INT_CAUSE);
 371
 372        if ((cause & F_PARITYERR) && mc5->parity_enabled) {
 373                CH_ALERT(adap, "MC5 parity error\n");
 374                mc5->stats.parity_err++;
 375        }
 376
 377        if (cause & F_REQQPARERR) {
 378                CH_ALERT(adap, "MC5 request queue parity error\n");
 379                mc5->stats.reqq_parity_err++;
 380        }
 381
 382        if (cause & F_DISPQPARERR) {
 383                CH_ALERT(adap, "MC5 dispatch queue parity error\n");
 384                mc5->stats.dispq_parity_err++;
 385        }
 386
 387        if (cause & F_ACTRGNFULL)
 388                mc5->stats.active_rgn_full++;
 389        if (cause & F_NFASRCHFAIL)
 390                mc5->stats.nfa_srch_err++;
 391        if (cause & F_UNKNOWNCMD)
 392                mc5->stats.unknown_cmd++;
 393        if (cause & F_DELACTEMPTY)
 394                mc5->stats.del_act_empty++;
 395        if (cause & MC5_INT_FATAL)
 396                t3_fatal_err(adap);
 397
 398        t3_write_reg(adap, A_MC5_DB_INT_CAUSE, cause);
 399}
 400
 401void t3_mc5_prep(struct adapter *adapter, struct mc5 *mc5, int mode)
 402{
 403#define K * 1024
 404
 405        static unsigned int tcam_part_size[] = {        /* in K 72-bit entries */
 406                64 K, 128 K, 256 K, 32 K
 407        };
 408
 409#undef K
 410
 411        u32 cfg = t3_read_reg(adapter, A_MC5_DB_CONFIG);
 412
 413        mc5->adapter = adapter;
 414        mc5->mode = (unsigned char)mode;
 415        mc5->part_type = (unsigned char)G_TMTYPE(cfg);
 416        if (cfg & F_TMTYPEHI)
 417                mc5->part_type |= 4;
 418
 419        mc5->tcam_size = tcam_part_size[G_TMPARTSIZE(cfg)];
 420        if (mode == MC5_MODE_144_BIT)
 421                mc5->tcam_size /= 2;
 422}
 423