Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (c) 2003-2008 Chelsio, Inc. All rights reserved.
0003  *
0004  * This software is available to you under a choice of one of two
0005  * licenses.  You may choose to be licensed under the terms of the GNU
0006  * General Public License (GPL) Version 2, available from the file
0007  * COPYING in the main directory of this source tree, or the
0008  * OpenIB.org BSD license below:
0009  *
0010  *     Redistribution and use in source and binary forms, with or
0011  *     without modification, are permitted provided that the following
0012  *     conditions are met:
0013  *
0014  *      - Redistributions of source code must retain the above
0015  *        copyright notice, this list of conditions and the following
0016  *        disclaimer.
0017  *
0018  *      - Redistributions in binary form must reproduce the above
0019  *        copyright notice, this list of conditions and the following
0020  *        disclaimer in the documentation and/or other materials
0021  *        provided with the distribution.
0022  *
0023  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
0024  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
0025  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
0026  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
0027  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
0028  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
0029  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
0030  * SOFTWARE.
0031  */
0032 #include "common.h"
0033 #include "regs.h"
0034 
0035 enum {
0036     IDT75P52100 = 4,
0037     IDT75N43102 = 5
0038 };
0039 
0040 /* DBGI command mode */
0041 enum {
0042     DBGI_MODE_MBUS = 0,
0043     DBGI_MODE_IDT52100 = 5
0044 };
0045 
0046 /* IDT 75P52100 commands */
0047 #define IDT_CMD_READ   0
0048 #define IDT_CMD_WRITE  1
0049 #define IDT_CMD_SEARCH 2
0050 #define IDT_CMD_LEARN  3
0051 
0052 /* IDT LAR register address and value for 144-bit mode (low 32 bits) */
0053 #define IDT_LAR_ADR0    0x180006
0054 #define IDT_LAR_MODE144 0xffff0000
0055 
0056 /* IDT SCR and SSR addresses (low 32 bits) */
0057 #define IDT_SCR_ADR0  0x180000
0058 #define IDT_SSR0_ADR0 0x180002
0059 #define IDT_SSR1_ADR0 0x180004
0060 
0061 /* IDT GMR base address (low 32 bits) */
0062 #define IDT_GMR_BASE_ADR0 0x180020
0063 
0064 /* IDT data and mask array base addresses (low 32 bits) */
0065 #define IDT_DATARY_BASE_ADR0 0
0066 #define IDT_MSKARY_BASE_ADR0 0x80000
0067 
0068 /* IDT 75N43102 commands */
0069 #define IDT4_CMD_SEARCH144 3
0070 #define IDT4_CMD_WRITE     4
0071 #define IDT4_CMD_READ      5
0072 
0073 /* IDT 75N43102 SCR address (low 32 bits) */
0074 #define IDT4_SCR_ADR0  0x3
0075 
0076 /* IDT 75N43102 GMR base addresses (low 32 bits) */
0077 #define IDT4_GMR_BASE0 0x10
0078 #define IDT4_GMR_BASE1 0x20
0079 #define IDT4_GMR_BASE2 0x30
0080 
0081 /* IDT 75N43102 data and mask array base addresses (low 32 bits) */
0082 #define IDT4_DATARY_BASE_ADR0 0x1000000
0083 #define IDT4_MSKARY_BASE_ADR0 0x2000000
0084 
0085 #define MAX_WRITE_ATTEMPTS 5
0086 
0087 #define MAX_ROUTES 2048
0088 
0089 /*
0090  * Issue a command to the TCAM and wait for its completion.  The address and
0091  * any data required by the command must have been setup by the caller.
0092  */
0093 static int mc5_cmd_write(struct adapter *adapter, u32 cmd)
0094 {
0095     t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_CMD, cmd);
0096     return t3_wait_op_done(adapter, A_MC5_DB_DBGI_RSP_STATUS,
0097                    F_DBGIRSPVALID, 1, MAX_WRITE_ATTEMPTS, 1);
0098 }
0099 
0100 static inline void dbgi_wr_data3(struct adapter *adapter, u32 v1, u32 v2,
0101                  u32 v3)
0102 {
0103     t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_DATA0, v1);
0104     t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_DATA1, v2);
0105     t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_DATA2, v3);
0106 }
0107 
0108 /*
0109  * Write data to the TCAM register at address (0, 0, addr_lo) using the TCAM
0110  * command cmd.  The data to be written must have been set up by the caller.
0111  * Returns -1 on failure, 0 on success.
0112  */
0113 static int mc5_write(struct adapter *adapter, u32 addr_lo, u32 cmd)
0114 {
0115     t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_ADDR0, addr_lo);
0116     if (mc5_cmd_write(adapter, cmd) == 0)
0117         return 0;
0118     CH_ERR(adapter, "MC5 timeout writing to TCAM address 0x%x\n",
0119            addr_lo);
0120     return -1;
0121 }
0122 
0123 static int init_mask_data_array(struct mc5 *mc5, u32 mask_array_base,
0124                 u32 data_array_base, u32 write_cmd,
0125                 int addr_shift)
0126 {
0127     unsigned int i;
0128     struct adapter *adap = mc5->adapter;
0129 
0130     /*
0131      * We need the size of the TCAM data and mask arrays in terms of
0132      * 72-bit entries.
0133      */
0134     unsigned int size72 = mc5->tcam_size;
0135     unsigned int server_base = t3_read_reg(adap, A_MC5_DB_SERVER_INDEX);
0136 
0137     if (mc5->mode == MC5_MODE_144_BIT) {
0138         size72 *= 2;    /* 1 144-bit entry is 2 72-bit entries */
0139         server_base *= 2;
0140     }
0141 
0142     /* Clear the data array */
0143     dbgi_wr_data3(adap, 0, 0, 0);
0144     for (i = 0; i < size72; i++)
0145         if (mc5_write(adap, data_array_base + (i << addr_shift),
0146                   write_cmd))
0147             return -1;
0148 
0149     /* Initialize the mask array. */
0150     dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0xff);
0151     for (i = 0; i < size72; i++) {
0152         if (i == server_base)   /* entering server or routing region */
0153             t3_write_reg(adap, A_MC5_DB_DBGI_REQ_DATA0,
0154                      mc5->mode == MC5_MODE_144_BIT ?
0155                      0xfffffff9 : 0xfffffffd);
0156         if (mc5_write(adap, mask_array_base + (i << addr_shift),
0157                   write_cmd))
0158             return -1;
0159     }
0160     return 0;
0161 }
0162 
0163 static int init_idt52100(struct mc5 *mc5)
0164 {
0165     int i;
0166     struct adapter *adap = mc5->adapter;
0167 
0168     t3_write_reg(adap, A_MC5_DB_RSP_LATENCY,
0169              V_RDLAT(0x15) | V_LRNLAT(0x15) | V_SRCHLAT(0x15));
0170     t3_write_reg(adap, A_MC5_DB_PART_ID_INDEX, 2);
0171 
0172     /*
0173      * Use GMRs 14-15 for ELOOKUP, GMRs 12-13 for SYN lookups, and
0174      * GMRs 8-9 for ACK- and AOPEN searches.
0175      */
0176     t3_write_reg(adap, A_MC5_DB_POPEN_DATA_WR_CMD, IDT_CMD_WRITE);
0177     t3_write_reg(adap, A_MC5_DB_POPEN_MASK_WR_CMD, IDT_CMD_WRITE);
0178     t3_write_reg(adap, A_MC5_DB_AOPEN_SRCH_CMD, IDT_CMD_SEARCH);
0179     t3_write_reg(adap, A_MC5_DB_AOPEN_LRN_CMD, IDT_CMD_LEARN);
0180     t3_write_reg(adap, A_MC5_DB_SYN_SRCH_CMD, IDT_CMD_SEARCH | 0x6000);
0181     t3_write_reg(adap, A_MC5_DB_SYN_LRN_CMD, IDT_CMD_LEARN);
0182     t3_write_reg(adap, A_MC5_DB_ACK_SRCH_CMD, IDT_CMD_SEARCH);
0183     t3_write_reg(adap, A_MC5_DB_ACK_LRN_CMD, IDT_CMD_LEARN);
0184     t3_write_reg(adap, A_MC5_DB_ILOOKUP_CMD, IDT_CMD_SEARCH);
0185     t3_write_reg(adap, A_MC5_DB_ELOOKUP_CMD, IDT_CMD_SEARCH | 0x7000);
0186     t3_write_reg(adap, A_MC5_DB_DATA_WRITE_CMD, IDT_CMD_WRITE);
0187     t3_write_reg(adap, A_MC5_DB_DATA_READ_CMD, IDT_CMD_READ);
0188 
0189     /* Set DBGI command mode for IDT TCAM. */
0190     t3_write_reg(adap, A_MC5_DB_DBGI_CONFIG, DBGI_MODE_IDT52100);
0191 
0192     /* Set up LAR */
0193     dbgi_wr_data3(adap, IDT_LAR_MODE144, 0, 0);
0194     if (mc5_write(adap, IDT_LAR_ADR0, IDT_CMD_WRITE))
0195         goto err;
0196 
0197     /* Set up SSRs */
0198     dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0);
0199     if (mc5_write(adap, IDT_SSR0_ADR0, IDT_CMD_WRITE) ||
0200         mc5_write(adap, IDT_SSR1_ADR0, IDT_CMD_WRITE))
0201         goto err;
0202 
0203     /* Set up GMRs */
0204     for (i = 0; i < 32; ++i) {
0205         if (i >= 12 && i < 15)
0206             dbgi_wr_data3(adap, 0xfffffff9, 0xffffffff, 0xff);
0207         else if (i == 15)
0208             dbgi_wr_data3(adap, 0xfffffff9, 0xffff8007, 0xff);
0209         else
0210             dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0xff);
0211 
0212         if (mc5_write(adap, IDT_GMR_BASE_ADR0 + i, IDT_CMD_WRITE))
0213             goto err;
0214     }
0215 
0216     /* Set up SCR */
0217     dbgi_wr_data3(adap, 1, 0, 0);
0218     if (mc5_write(adap, IDT_SCR_ADR0, IDT_CMD_WRITE))
0219         goto err;
0220 
0221     return init_mask_data_array(mc5, IDT_MSKARY_BASE_ADR0,
0222                     IDT_DATARY_BASE_ADR0, IDT_CMD_WRITE, 0);
0223 err:
0224     return -EIO;
0225 }
0226 
0227 static int init_idt43102(struct mc5 *mc5)
0228 {
0229     int i;
0230     struct adapter *adap = mc5->adapter;
0231 
0232     t3_write_reg(adap, A_MC5_DB_RSP_LATENCY,
0233              adap->params.rev == 0 ? V_RDLAT(0xd) | V_SRCHLAT(0x11) :
0234              V_RDLAT(0xd) | V_SRCHLAT(0x12));
0235 
0236     /*
0237      * Use GMRs 24-25 for ELOOKUP, GMRs 20-21 for SYN lookups, and no mask
0238      * for ACK- and AOPEN searches.
0239      */
0240     t3_write_reg(adap, A_MC5_DB_POPEN_DATA_WR_CMD, IDT4_CMD_WRITE);
0241     t3_write_reg(adap, A_MC5_DB_POPEN_MASK_WR_CMD, IDT4_CMD_WRITE);
0242     t3_write_reg(adap, A_MC5_DB_AOPEN_SRCH_CMD,
0243              IDT4_CMD_SEARCH144 | 0x3800);
0244     t3_write_reg(adap, A_MC5_DB_SYN_SRCH_CMD, IDT4_CMD_SEARCH144);
0245     t3_write_reg(adap, A_MC5_DB_ACK_SRCH_CMD, IDT4_CMD_SEARCH144 | 0x3800);
0246     t3_write_reg(adap, A_MC5_DB_ILOOKUP_CMD, IDT4_CMD_SEARCH144 | 0x3800);
0247     t3_write_reg(adap, A_MC5_DB_ELOOKUP_CMD, IDT4_CMD_SEARCH144 | 0x800);
0248     t3_write_reg(adap, A_MC5_DB_DATA_WRITE_CMD, IDT4_CMD_WRITE);
0249     t3_write_reg(adap, A_MC5_DB_DATA_READ_CMD, IDT4_CMD_READ);
0250 
0251     t3_write_reg(adap, A_MC5_DB_PART_ID_INDEX, 3);
0252 
0253     /* Set DBGI command mode for IDT TCAM. */
0254     t3_write_reg(adap, A_MC5_DB_DBGI_CONFIG, DBGI_MODE_IDT52100);
0255 
0256     /* Set up GMRs */
0257     dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0xff);
0258     for (i = 0; i < 7; ++i)
0259         if (mc5_write(adap, IDT4_GMR_BASE0 + i, IDT4_CMD_WRITE))
0260             goto err;
0261 
0262     for (i = 0; i < 4; ++i)
0263         if (mc5_write(adap, IDT4_GMR_BASE2 + i, IDT4_CMD_WRITE))
0264             goto err;
0265 
0266     dbgi_wr_data3(adap, 0xfffffff9, 0xffffffff, 0xff);
0267     if (mc5_write(adap, IDT4_GMR_BASE1, IDT4_CMD_WRITE) ||
0268         mc5_write(adap, IDT4_GMR_BASE1 + 1, IDT4_CMD_WRITE) ||
0269         mc5_write(adap, IDT4_GMR_BASE1 + 4, IDT4_CMD_WRITE))
0270         goto err;
0271 
0272     dbgi_wr_data3(adap, 0xfffffff9, 0xffff8007, 0xff);
0273     if (mc5_write(adap, IDT4_GMR_BASE1 + 5, IDT4_CMD_WRITE))
0274         goto err;
0275 
0276     /* Set up SCR */
0277     dbgi_wr_data3(adap, 0xf0000000, 0, 0);
0278     if (mc5_write(adap, IDT4_SCR_ADR0, IDT4_CMD_WRITE))
0279         goto err;
0280 
0281     return init_mask_data_array(mc5, IDT4_MSKARY_BASE_ADR0,
0282                     IDT4_DATARY_BASE_ADR0, IDT4_CMD_WRITE, 1);
0283 err:
0284     return -EIO;
0285 }
0286 
0287 /* Put MC5 in DBGI mode. */
0288 static inline void mc5_dbgi_mode_enable(const struct mc5 *mc5)
0289 {
0290     t3_write_reg(mc5->adapter, A_MC5_DB_CONFIG,
0291              V_TMMODE(mc5->mode == MC5_MODE_72_BIT) | F_DBGIEN);
0292 }
0293 
0294 /* Put MC5 in M-Bus mode. */
0295 static void mc5_dbgi_mode_disable(const struct mc5 *mc5)
0296 {
0297     t3_write_reg(mc5->adapter, A_MC5_DB_CONFIG,
0298              V_TMMODE(mc5->mode == MC5_MODE_72_BIT) |
0299              V_COMPEN(mc5->mode == MC5_MODE_72_BIT) |
0300              V_PRTYEN(mc5->parity_enabled) | F_MBUSEN);
0301 }
0302 
0303 /*
0304  * Initialization that requires the OS and protocol layers to already
0305  * be initialized goes here.
0306  */
0307 int t3_mc5_init(struct mc5 *mc5, unsigned int nservers, unsigned int nfilters,
0308         unsigned int nroutes)
0309 {
0310     u32 cfg;
0311     int err;
0312     unsigned int tcam_size = mc5->tcam_size;
0313     struct adapter *adap = mc5->adapter;
0314 
0315     if (!tcam_size)
0316         return 0;
0317 
0318     if (nroutes > MAX_ROUTES || nroutes + nservers + nfilters > tcam_size)
0319         return -EINVAL;
0320 
0321     /* Reset the TCAM */
0322     cfg = t3_read_reg(adap, A_MC5_DB_CONFIG) & ~F_TMMODE;
0323     cfg |= V_TMMODE(mc5->mode == MC5_MODE_72_BIT) | F_TMRST;
0324     t3_write_reg(adap, A_MC5_DB_CONFIG, cfg);
0325     if (t3_wait_op_done(adap, A_MC5_DB_CONFIG, F_TMRDY, 1, 500, 0)) {
0326         CH_ERR(adap, "TCAM reset timed out\n");
0327         return -1;
0328     }
0329 
0330     t3_write_reg(adap, A_MC5_DB_ROUTING_TABLE_INDEX, tcam_size - nroutes);
0331     t3_write_reg(adap, A_MC5_DB_FILTER_TABLE,
0332              tcam_size - nroutes - nfilters);
0333     t3_write_reg(adap, A_MC5_DB_SERVER_INDEX,
0334              tcam_size - nroutes - nfilters - nservers);
0335 
0336     mc5->parity_enabled = 1;
0337 
0338     /* All the TCAM addresses we access have only the low 32 bits non 0 */
0339     t3_write_reg(adap, A_MC5_DB_DBGI_REQ_ADDR1, 0);
0340     t3_write_reg(adap, A_MC5_DB_DBGI_REQ_ADDR2, 0);
0341 
0342     mc5_dbgi_mode_enable(mc5);
0343 
0344     switch (mc5->part_type) {
0345     case IDT75P52100:
0346         err = init_idt52100(mc5);
0347         break;
0348     case IDT75N43102:
0349         err = init_idt43102(mc5);
0350         break;
0351     default:
0352         CH_ERR(adap, "Unsupported TCAM type %d\n", mc5->part_type);
0353         err = -EINVAL;
0354         break;
0355     }
0356 
0357     mc5_dbgi_mode_disable(mc5);
0358     return err;
0359 }
0360 
0361 
0362 #define MC5_INT_FATAL (F_PARITYERR | F_REQQPARERR | F_DISPQPARERR)
0363 
0364 /*
0365  * MC5 interrupt handler
0366  */
0367 void t3_mc5_intr_handler(struct mc5 *mc5)
0368 {
0369     struct adapter *adap = mc5->adapter;
0370     u32 cause = t3_read_reg(adap, A_MC5_DB_INT_CAUSE);
0371 
0372     if ((cause & F_PARITYERR) && mc5->parity_enabled) {
0373         CH_ALERT(adap, "MC5 parity error\n");
0374         mc5->stats.parity_err++;
0375     }
0376 
0377     if (cause & F_REQQPARERR) {
0378         CH_ALERT(adap, "MC5 request queue parity error\n");
0379         mc5->stats.reqq_parity_err++;
0380     }
0381 
0382     if (cause & F_DISPQPARERR) {
0383         CH_ALERT(adap, "MC5 dispatch queue parity error\n");
0384         mc5->stats.dispq_parity_err++;
0385     }
0386 
0387     if (cause & F_ACTRGNFULL)
0388         mc5->stats.active_rgn_full++;
0389     if (cause & F_NFASRCHFAIL)
0390         mc5->stats.nfa_srch_err++;
0391     if (cause & F_UNKNOWNCMD)
0392         mc5->stats.unknown_cmd++;
0393     if (cause & F_DELACTEMPTY)
0394         mc5->stats.del_act_empty++;
0395     if (cause & MC5_INT_FATAL)
0396         t3_fatal_err(adap);
0397 
0398     t3_write_reg(adap, A_MC5_DB_INT_CAUSE, cause);
0399 }
0400 
0401 void t3_mc5_prep(struct adapter *adapter, struct mc5 *mc5, int mode)
0402 {
0403 #define K * 1024
0404 
0405     static unsigned int tcam_part_size[] = {    /* in K 72-bit entries */
0406         64 K, 128 K, 256 K, 32 K
0407     };
0408 
0409 #undef K
0410 
0411     u32 cfg = t3_read_reg(adapter, A_MC5_DB_CONFIG);
0412 
0413     mc5->adapter = adapter;
0414     mc5->mode = (unsigned char)mode;
0415     mc5->part_type = (unsigned char)G_TMTYPE(cfg);
0416     if (cfg & F_TMTYPEHI)
0417         mc5->part_type |= 4;
0418 
0419     mc5->tcam_size = tcam_part_size[G_TMPARTSIZE(cfg)];
0420     if (mode == MC5_MODE_144_BIT)
0421         mc5->tcam_size /= 2;
0422 }