0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032 #include "common.h"
0033 #include "regs.h"
0034
0035 enum {
0036 IDT75P52100 = 4,
0037 IDT75N43102 = 5
0038 };
0039
0040
0041 enum {
0042 DBGI_MODE_MBUS = 0,
0043 DBGI_MODE_IDT52100 = 5
0044 };
0045
0046
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
0053 #define IDT_LAR_ADR0 0x180006
0054 #define IDT_LAR_MODE144 0xffff0000
0055
0056
0057 #define IDT_SCR_ADR0 0x180000
0058 #define IDT_SSR0_ADR0 0x180002
0059 #define IDT_SSR1_ADR0 0x180004
0060
0061
0062 #define IDT_GMR_BASE_ADR0 0x180020
0063
0064
0065 #define IDT_DATARY_BASE_ADR0 0
0066 #define IDT_MSKARY_BASE_ADR0 0x80000
0067
0068
0069 #define IDT4_CMD_SEARCH144 3
0070 #define IDT4_CMD_WRITE 4
0071 #define IDT4_CMD_READ 5
0072
0073
0074 #define IDT4_SCR_ADR0 0x3
0075
0076
0077 #define IDT4_GMR_BASE0 0x10
0078 #define IDT4_GMR_BASE1 0x20
0079 #define IDT4_GMR_BASE2 0x30
0080
0081
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
0091
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
0110
0111
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
0132
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;
0139 server_base *= 2;
0140 }
0141
0142
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
0150 dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0xff);
0151 for (i = 0; i < size72; i++) {
0152 if (i == server_base)
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
0174
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
0190 t3_write_reg(adap, A_MC5_DB_DBGI_CONFIG, DBGI_MODE_IDT52100);
0191
0192
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
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
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
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
0238
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
0254 t3_write_reg(adap, A_MC5_DB_DBGI_CONFIG, DBGI_MODE_IDT52100);
0255
0256
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
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
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
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
0305
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
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
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
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[] = {
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 }