18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright (c) 2003-2008 Chelsio, Inc. All rights reserved. 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * This software is available to you under a choice of one of two 58c2ecf20Sopenharmony_ci * licenses. You may choose to be licensed under the terms of the GNU 68c2ecf20Sopenharmony_ci * General Public License (GPL) Version 2, available from the file 78c2ecf20Sopenharmony_ci * COPYING in the main directory of this source tree, or the 88c2ecf20Sopenharmony_ci * OpenIB.org BSD license below: 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or 118c2ecf20Sopenharmony_ci * without modification, are permitted provided that the following 128c2ecf20Sopenharmony_ci * conditions are met: 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * - Redistributions of source code must retain the above 158c2ecf20Sopenharmony_ci * copyright notice, this list of conditions and the following 168c2ecf20Sopenharmony_ci * disclaimer. 178c2ecf20Sopenharmony_ci * 188c2ecf20Sopenharmony_ci * - Redistributions in binary form must reproduce the above 198c2ecf20Sopenharmony_ci * copyright notice, this list of conditions and the following 208c2ecf20Sopenharmony_ci * disclaimer in the documentation and/or other materials 218c2ecf20Sopenharmony_ci * provided with the distribution. 228c2ecf20Sopenharmony_ci * 238c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 248c2ecf20Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 258c2ecf20Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 268c2ecf20Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 278c2ecf20Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 288c2ecf20Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 298c2ecf20Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 308c2ecf20Sopenharmony_ci * SOFTWARE. 318c2ecf20Sopenharmony_ci */ 328c2ecf20Sopenharmony_ci#include "common.h" 338c2ecf20Sopenharmony_ci#include "regs.h" 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_cienum { 368c2ecf20Sopenharmony_ci IDT75P52100 = 4, 378c2ecf20Sopenharmony_ci IDT75N43102 = 5 388c2ecf20Sopenharmony_ci}; 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci/* DBGI command mode */ 418c2ecf20Sopenharmony_cienum { 428c2ecf20Sopenharmony_ci DBGI_MODE_MBUS = 0, 438c2ecf20Sopenharmony_ci DBGI_MODE_IDT52100 = 5 448c2ecf20Sopenharmony_ci}; 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci/* IDT 75P52100 commands */ 478c2ecf20Sopenharmony_ci#define IDT_CMD_READ 0 488c2ecf20Sopenharmony_ci#define IDT_CMD_WRITE 1 498c2ecf20Sopenharmony_ci#define IDT_CMD_SEARCH 2 508c2ecf20Sopenharmony_ci#define IDT_CMD_LEARN 3 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci/* IDT LAR register address and value for 144-bit mode (low 32 bits) */ 538c2ecf20Sopenharmony_ci#define IDT_LAR_ADR0 0x180006 548c2ecf20Sopenharmony_ci#define IDT_LAR_MODE144 0xffff0000 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci/* IDT SCR and SSR addresses (low 32 bits) */ 578c2ecf20Sopenharmony_ci#define IDT_SCR_ADR0 0x180000 588c2ecf20Sopenharmony_ci#define IDT_SSR0_ADR0 0x180002 598c2ecf20Sopenharmony_ci#define IDT_SSR1_ADR0 0x180004 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci/* IDT GMR base address (low 32 bits) */ 628c2ecf20Sopenharmony_ci#define IDT_GMR_BASE_ADR0 0x180020 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci/* IDT data and mask array base addresses (low 32 bits) */ 658c2ecf20Sopenharmony_ci#define IDT_DATARY_BASE_ADR0 0 668c2ecf20Sopenharmony_ci#define IDT_MSKARY_BASE_ADR0 0x80000 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci/* IDT 75N43102 commands */ 698c2ecf20Sopenharmony_ci#define IDT4_CMD_SEARCH144 3 708c2ecf20Sopenharmony_ci#define IDT4_CMD_WRITE 4 718c2ecf20Sopenharmony_ci#define IDT4_CMD_READ 5 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci/* IDT 75N43102 SCR address (low 32 bits) */ 748c2ecf20Sopenharmony_ci#define IDT4_SCR_ADR0 0x3 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci/* IDT 75N43102 GMR base addresses (low 32 bits) */ 778c2ecf20Sopenharmony_ci#define IDT4_GMR_BASE0 0x10 788c2ecf20Sopenharmony_ci#define IDT4_GMR_BASE1 0x20 798c2ecf20Sopenharmony_ci#define IDT4_GMR_BASE2 0x30 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci/* IDT 75N43102 data and mask array base addresses (low 32 bits) */ 828c2ecf20Sopenharmony_ci#define IDT4_DATARY_BASE_ADR0 0x1000000 838c2ecf20Sopenharmony_ci#define IDT4_MSKARY_BASE_ADR0 0x2000000 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci#define MAX_WRITE_ATTEMPTS 5 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci#define MAX_ROUTES 2048 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci/* 908c2ecf20Sopenharmony_ci * Issue a command to the TCAM and wait for its completion. The address and 918c2ecf20Sopenharmony_ci * any data required by the command must have been setup by the caller. 928c2ecf20Sopenharmony_ci */ 938c2ecf20Sopenharmony_cistatic int mc5_cmd_write(struct adapter *adapter, u32 cmd) 948c2ecf20Sopenharmony_ci{ 958c2ecf20Sopenharmony_ci t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_CMD, cmd); 968c2ecf20Sopenharmony_ci return t3_wait_op_done(adapter, A_MC5_DB_DBGI_RSP_STATUS, 978c2ecf20Sopenharmony_ci F_DBGIRSPVALID, 1, MAX_WRITE_ATTEMPTS, 1); 988c2ecf20Sopenharmony_ci} 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_cistatic inline void dbgi_wr_data3(struct adapter *adapter, u32 v1, u32 v2, 1018c2ecf20Sopenharmony_ci u32 v3) 1028c2ecf20Sopenharmony_ci{ 1038c2ecf20Sopenharmony_ci t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_DATA0, v1); 1048c2ecf20Sopenharmony_ci t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_DATA1, v2); 1058c2ecf20Sopenharmony_ci t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_DATA2, v3); 1068c2ecf20Sopenharmony_ci} 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci/* 1098c2ecf20Sopenharmony_ci * Write data to the TCAM register at address (0, 0, addr_lo) using the TCAM 1108c2ecf20Sopenharmony_ci * command cmd. The data to be written must have been set up by the caller. 1118c2ecf20Sopenharmony_ci * Returns -1 on failure, 0 on success. 1128c2ecf20Sopenharmony_ci */ 1138c2ecf20Sopenharmony_cistatic int mc5_write(struct adapter *adapter, u32 addr_lo, u32 cmd) 1148c2ecf20Sopenharmony_ci{ 1158c2ecf20Sopenharmony_ci t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_ADDR0, addr_lo); 1168c2ecf20Sopenharmony_ci if (mc5_cmd_write(adapter, cmd) == 0) 1178c2ecf20Sopenharmony_ci return 0; 1188c2ecf20Sopenharmony_ci CH_ERR(adapter, "MC5 timeout writing to TCAM address 0x%x\n", 1198c2ecf20Sopenharmony_ci addr_lo); 1208c2ecf20Sopenharmony_ci return -1; 1218c2ecf20Sopenharmony_ci} 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_cistatic int init_mask_data_array(struct mc5 *mc5, u32 mask_array_base, 1248c2ecf20Sopenharmony_ci u32 data_array_base, u32 write_cmd, 1258c2ecf20Sopenharmony_ci int addr_shift) 1268c2ecf20Sopenharmony_ci{ 1278c2ecf20Sopenharmony_ci unsigned int i; 1288c2ecf20Sopenharmony_ci struct adapter *adap = mc5->adapter; 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci /* 1318c2ecf20Sopenharmony_ci * We need the size of the TCAM data and mask arrays in terms of 1328c2ecf20Sopenharmony_ci * 72-bit entries. 1338c2ecf20Sopenharmony_ci */ 1348c2ecf20Sopenharmony_ci unsigned int size72 = mc5->tcam_size; 1358c2ecf20Sopenharmony_ci unsigned int server_base = t3_read_reg(adap, A_MC5_DB_SERVER_INDEX); 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci if (mc5->mode == MC5_MODE_144_BIT) { 1388c2ecf20Sopenharmony_ci size72 *= 2; /* 1 144-bit entry is 2 72-bit entries */ 1398c2ecf20Sopenharmony_ci server_base *= 2; 1408c2ecf20Sopenharmony_ci } 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci /* Clear the data array */ 1438c2ecf20Sopenharmony_ci dbgi_wr_data3(adap, 0, 0, 0); 1448c2ecf20Sopenharmony_ci for (i = 0; i < size72; i++) 1458c2ecf20Sopenharmony_ci if (mc5_write(adap, data_array_base + (i << addr_shift), 1468c2ecf20Sopenharmony_ci write_cmd)) 1478c2ecf20Sopenharmony_ci return -1; 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci /* Initialize the mask array. */ 1508c2ecf20Sopenharmony_ci dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0xff); 1518c2ecf20Sopenharmony_ci for (i = 0; i < size72; i++) { 1528c2ecf20Sopenharmony_ci if (i == server_base) /* entering server or routing region */ 1538c2ecf20Sopenharmony_ci t3_write_reg(adap, A_MC5_DB_DBGI_REQ_DATA0, 1548c2ecf20Sopenharmony_ci mc5->mode == MC5_MODE_144_BIT ? 1558c2ecf20Sopenharmony_ci 0xfffffff9 : 0xfffffffd); 1568c2ecf20Sopenharmony_ci if (mc5_write(adap, mask_array_base + (i << addr_shift), 1578c2ecf20Sopenharmony_ci write_cmd)) 1588c2ecf20Sopenharmony_ci return -1; 1598c2ecf20Sopenharmony_ci } 1608c2ecf20Sopenharmony_ci return 0; 1618c2ecf20Sopenharmony_ci} 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_cistatic int init_idt52100(struct mc5 *mc5) 1648c2ecf20Sopenharmony_ci{ 1658c2ecf20Sopenharmony_ci int i; 1668c2ecf20Sopenharmony_ci struct adapter *adap = mc5->adapter; 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci t3_write_reg(adap, A_MC5_DB_RSP_LATENCY, 1698c2ecf20Sopenharmony_ci V_RDLAT(0x15) | V_LRNLAT(0x15) | V_SRCHLAT(0x15)); 1708c2ecf20Sopenharmony_ci t3_write_reg(adap, A_MC5_DB_PART_ID_INDEX, 2); 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci /* 1738c2ecf20Sopenharmony_ci * Use GMRs 14-15 for ELOOKUP, GMRs 12-13 for SYN lookups, and 1748c2ecf20Sopenharmony_ci * GMRs 8-9 for ACK- and AOPEN searches. 1758c2ecf20Sopenharmony_ci */ 1768c2ecf20Sopenharmony_ci t3_write_reg(adap, A_MC5_DB_POPEN_DATA_WR_CMD, IDT_CMD_WRITE); 1778c2ecf20Sopenharmony_ci t3_write_reg(adap, A_MC5_DB_POPEN_MASK_WR_CMD, IDT_CMD_WRITE); 1788c2ecf20Sopenharmony_ci t3_write_reg(adap, A_MC5_DB_AOPEN_SRCH_CMD, IDT_CMD_SEARCH); 1798c2ecf20Sopenharmony_ci t3_write_reg(adap, A_MC5_DB_AOPEN_LRN_CMD, IDT_CMD_LEARN); 1808c2ecf20Sopenharmony_ci t3_write_reg(adap, A_MC5_DB_SYN_SRCH_CMD, IDT_CMD_SEARCH | 0x6000); 1818c2ecf20Sopenharmony_ci t3_write_reg(adap, A_MC5_DB_SYN_LRN_CMD, IDT_CMD_LEARN); 1828c2ecf20Sopenharmony_ci t3_write_reg(adap, A_MC5_DB_ACK_SRCH_CMD, IDT_CMD_SEARCH); 1838c2ecf20Sopenharmony_ci t3_write_reg(adap, A_MC5_DB_ACK_LRN_CMD, IDT_CMD_LEARN); 1848c2ecf20Sopenharmony_ci t3_write_reg(adap, A_MC5_DB_ILOOKUP_CMD, IDT_CMD_SEARCH); 1858c2ecf20Sopenharmony_ci t3_write_reg(adap, A_MC5_DB_ELOOKUP_CMD, IDT_CMD_SEARCH | 0x7000); 1868c2ecf20Sopenharmony_ci t3_write_reg(adap, A_MC5_DB_DATA_WRITE_CMD, IDT_CMD_WRITE); 1878c2ecf20Sopenharmony_ci t3_write_reg(adap, A_MC5_DB_DATA_READ_CMD, IDT_CMD_READ); 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci /* Set DBGI command mode for IDT TCAM. */ 1908c2ecf20Sopenharmony_ci t3_write_reg(adap, A_MC5_DB_DBGI_CONFIG, DBGI_MODE_IDT52100); 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci /* Set up LAR */ 1938c2ecf20Sopenharmony_ci dbgi_wr_data3(adap, IDT_LAR_MODE144, 0, 0); 1948c2ecf20Sopenharmony_ci if (mc5_write(adap, IDT_LAR_ADR0, IDT_CMD_WRITE)) 1958c2ecf20Sopenharmony_ci goto err; 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci /* Set up SSRs */ 1988c2ecf20Sopenharmony_ci dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0); 1998c2ecf20Sopenharmony_ci if (mc5_write(adap, IDT_SSR0_ADR0, IDT_CMD_WRITE) || 2008c2ecf20Sopenharmony_ci mc5_write(adap, IDT_SSR1_ADR0, IDT_CMD_WRITE)) 2018c2ecf20Sopenharmony_ci goto err; 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci /* Set up GMRs */ 2048c2ecf20Sopenharmony_ci for (i = 0; i < 32; ++i) { 2058c2ecf20Sopenharmony_ci if (i >= 12 && i < 15) 2068c2ecf20Sopenharmony_ci dbgi_wr_data3(adap, 0xfffffff9, 0xffffffff, 0xff); 2078c2ecf20Sopenharmony_ci else if (i == 15) 2088c2ecf20Sopenharmony_ci dbgi_wr_data3(adap, 0xfffffff9, 0xffff8007, 0xff); 2098c2ecf20Sopenharmony_ci else 2108c2ecf20Sopenharmony_ci dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0xff); 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci if (mc5_write(adap, IDT_GMR_BASE_ADR0 + i, IDT_CMD_WRITE)) 2138c2ecf20Sopenharmony_ci goto err; 2148c2ecf20Sopenharmony_ci } 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci /* Set up SCR */ 2178c2ecf20Sopenharmony_ci dbgi_wr_data3(adap, 1, 0, 0); 2188c2ecf20Sopenharmony_ci if (mc5_write(adap, IDT_SCR_ADR0, IDT_CMD_WRITE)) 2198c2ecf20Sopenharmony_ci goto err; 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci return init_mask_data_array(mc5, IDT_MSKARY_BASE_ADR0, 2228c2ecf20Sopenharmony_ci IDT_DATARY_BASE_ADR0, IDT_CMD_WRITE, 0); 2238c2ecf20Sopenharmony_cierr: 2248c2ecf20Sopenharmony_ci return -EIO; 2258c2ecf20Sopenharmony_ci} 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_cistatic int init_idt43102(struct mc5 *mc5) 2288c2ecf20Sopenharmony_ci{ 2298c2ecf20Sopenharmony_ci int i; 2308c2ecf20Sopenharmony_ci struct adapter *adap = mc5->adapter; 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci t3_write_reg(adap, A_MC5_DB_RSP_LATENCY, 2338c2ecf20Sopenharmony_ci adap->params.rev == 0 ? V_RDLAT(0xd) | V_SRCHLAT(0x11) : 2348c2ecf20Sopenharmony_ci V_RDLAT(0xd) | V_SRCHLAT(0x12)); 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci /* 2378c2ecf20Sopenharmony_ci * Use GMRs 24-25 for ELOOKUP, GMRs 20-21 for SYN lookups, and no mask 2388c2ecf20Sopenharmony_ci * for ACK- and AOPEN searches. 2398c2ecf20Sopenharmony_ci */ 2408c2ecf20Sopenharmony_ci t3_write_reg(adap, A_MC5_DB_POPEN_DATA_WR_CMD, IDT4_CMD_WRITE); 2418c2ecf20Sopenharmony_ci t3_write_reg(adap, A_MC5_DB_POPEN_MASK_WR_CMD, IDT4_CMD_WRITE); 2428c2ecf20Sopenharmony_ci t3_write_reg(adap, A_MC5_DB_AOPEN_SRCH_CMD, 2438c2ecf20Sopenharmony_ci IDT4_CMD_SEARCH144 | 0x3800); 2448c2ecf20Sopenharmony_ci t3_write_reg(adap, A_MC5_DB_SYN_SRCH_CMD, IDT4_CMD_SEARCH144); 2458c2ecf20Sopenharmony_ci t3_write_reg(adap, A_MC5_DB_ACK_SRCH_CMD, IDT4_CMD_SEARCH144 | 0x3800); 2468c2ecf20Sopenharmony_ci t3_write_reg(adap, A_MC5_DB_ILOOKUP_CMD, IDT4_CMD_SEARCH144 | 0x3800); 2478c2ecf20Sopenharmony_ci t3_write_reg(adap, A_MC5_DB_ELOOKUP_CMD, IDT4_CMD_SEARCH144 | 0x800); 2488c2ecf20Sopenharmony_ci t3_write_reg(adap, A_MC5_DB_DATA_WRITE_CMD, IDT4_CMD_WRITE); 2498c2ecf20Sopenharmony_ci t3_write_reg(adap, A_MC5_DB_DATA_READ_CMD, IDT4_CMD_READ); 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci t3_write_reg(adap, A_MC5_DB_PART_ID_INDEX, 3); 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci /* Set DBGI command mode for IDT TCAM. */ 2548c2ecf20Sopenharmony_ci t3_write_reg(adap, A_MC5_DB_DBGI_CONFIG, DBGI_MODE_IDT52100); 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci /* Set up GMRs */ 2578c2ecf20Sopenharmony_ci dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0xff); 2588c2ecf20Sopenharmony_ci for (i = 0; i < 7; ++i) 2598c2ecf20Sopenharmony_ci if (mc5_write(adap, IDT4_GMR_BASE0 + i, IDT4_CMD_WRITE)) 2608c2ecf20Sopenharmony_ci goto err; 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci for (i = 0; i < 4; ++i) 2638c2ecf20Sopenharmony_ci if (mc5_write(adap, IDT4_GMR_BASE2 + i, IDT4_CMD_WRITE)) 2648c2ecf20Sopenharmony_ci goto err; 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci dbgi_wr_data3(adap, 0xfffffff9, 0xffffffff, 0xff); 2678c2ecf20Sopenharmony_ci if (mc5_write(adap, IDT4_GMR_BASE1, IDT4_CMD_WRITE) || 2688c2ecf20Sopenharmony_ci mc5_write(adap, IDT4_GMR_BASE1 + 1, IDT4_CMD_WRITE) || 2698c2ecf20Sopenharmony_ci mc5_write(adap, IDT4_GMR_BASE1 + 4, IDT4_CMD_WRITE)) 2708c2ecf20Sopenharmony_ci goto err; 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci dbgi_wr_data3(adap, 0xfffffff9, 0xffff8007, 0xff); 2738c2ecf20Sopenharmony_ci if (mc5_write(adap, IDT4_GMR_BASE1 + 5, IDT4_CMD_WRITE)) 2748c2ecf20Sopenharmony_ci goto err; 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci /* Set up SCR */ 2778c2ecf20Sopenharmony_ci dbgi_wr_data3(adap, 0xf0000000, 0, 0); 2788c2ecf20Sopenharmony_ci if (mc5_write(adap, IDT4_SCR_ADR0, IDT4_CMD_WRITE)) 2798c2ecf20Sopenharmony_ci goto err; 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci return init_mask_data_array(mc5, IDT4_MSKARY_BASE_ADR0, 2828c2ecf20Sopenharmony_ci IDT4_DATARY_BASE_ADR0, IDT4_CMD_WRITE, 1); 2838c2ecf20Sopenharmony_cierr: 2848c2ecf20Sopenharmony_ci return -EIO; 2858c2ecf20Sopenharmony_ci} 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci/* Put MC5 in DBGI mode. */ 2888c2ecf20Sopenharmony_cistatic inline void mc5_dbgi_mode_enable(const struct mc5 *mc5) 2898c2ecf20Sopenharmony_ci{ 2908c2ecf20Sopenharmony_ci t3_write_reg(mc5->adapter, A_MC5_DB_CONFIG, 2918c2ecf20Sopenharmony_ci V_TMMODE(mc5->mode == MC5_MODE_72_BIT) | F_DBGIEN); 2928c2ecf20Sopenharmony_ci} 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci/* Put MC5 in M-Bus mode. */ 2958c2ecf20Sopenharmony_cistatic void mc5_dbgi_mode_disable(const struct mc5 *mc5) 2968c2ecf20Sopenharmony_ci{ 2978c2ecf20Sopenharmony_ci t3_write_reg(mc5->adapter, A_MC5_DB_CONFIG, 2988c2ecf20Sopenharmony_ci V_TMMODE(mc5->mode == MC5_MODE_72_BIT) | 2998c2ecf20Sopenharmony_ci V_COMPEN(mc5->mode == MC5_MODE_72_BIT) | 3008c2ecf20Sopenharmony_ci V_PRTYEN(mc5->parity_enabled) | F_MBUSEN); 3018c2ecf20Sopenharmony_ci} 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci/* 3048c2ecf20Sopenharmony_ci * Initialization that requires the OS and protocol layers to already 3058c2ecf20Sopenharmony_ci * be initialized goes here. 3068c2ecf20Sopenharmony_ci */ 3078c2ecf20Sopenharmony_ciint t3_mc5_init(struct mc5 *mc5, unsigned int nservers, unsigned int nfilters, 3088c2ecf20Sopenharmony_ci unsigned int nroutes) 3098c2ecf20Sopenharmony_ci{ 3108c2ecf20Sopenharmony_ci u32 cfg; 3118c2ecf20Sopenharmony_ci int err; 3128c2ecf20Sopenharmony_ci unsigned int tcam_size = mc5->tcam_size; 3138c2ecf20Sopenharmony_ci struct adapter *adap = mc5->adapter; 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci if (!tcam_size) 3168c2ecf20Sopenharmony_ci return 0; 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci if (nroutes > MAX_ROUTES || nroutes + nservers + nfilters > tcam_size) 3198c2ecf20Sopenharmony_ci return -EINVAL; 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci /* Reset the TCAM */ 3228c2ecf20Sopenharmony_ci cfg = t3_read_reg(adap, A_MC5_DB_CONFIG) & ~F_TMMODE; 3238c2ecf20Sopenharmony_ci cfg |= V_TMMODE(mc5->mode == MC5_MODE_72_BIT) | F_TMRST; 3248c2ecf20Sopenharmony_ci t3_write_reg(adap, A_MC5_DB_CONFIG, cfg); 3258c2ecf20Sopenharmony_ci if (t3_wait_op_done(adap, A_MC5_DB_CONFIG, F_TMRDY, 1, 500, 0)) { 3268c2ecf20Sopenharmony_ci CH_ERR(adap, "TCAM reset timed out\n"); 3278c2ecf20Sopenharmony_ci return -1; 3288c2ecf20Sopenharmony_ci } 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci t3_write_reg(adap, A_MC5_DB_ROUTING_TABLE_INDEX, tcam_size - nroutes); 3318c2ecf20Sopenharmony_ci t3_write_reg(adap, A_MC5_DB_FILTER_TABLE, 3328c2ecf20Sopenharmony_ci tcam_size - nroutes - nfilters); 3338c2ecf20Sopenharmony_ci t3_write_reg(adap, A_MC5_DB_SERVER_INDEX, 3348c2ecf20Sopenharmony_ci tcam_size - nroutes - nfilters - nservers); 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci mc5->parity_enabled = 1; 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci /* All the TCAM addresses we access have only the low 32 bits non 0 */ 3398c2ecf20Sopenharmony_ci t3_write_reg(adap, A_MC5_DB_DBGI_REQ_ADDR1, 0); 3408c2ecf20Sopenharmony_ci t3_write_reg(adap, A_MC5_DB_DBGI_REQ_ADDR2, 0); 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci mc5_dbgi_mode_enable(mc5); 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci switch (mc5->part_type) { 3458c2ecf20Sopenharmony_ci case IDT75P52100: 3468c2ecf20Sopenharmony_ci err = init_idt52100(mc5); 3478c2ecf20Sopenharmony_ci break; 3488c2ecf20Sopenharmony_ci case IDT75N43102: 3498c2ecf20Sopenharmony_ci err = init_idt43102(mc5); 3508c2ecf20Sopenharmony_ci break; 3518c2ecf20Sopenharmony_ci default: 3528c2ecf20Sopenharmony_ci CH_ERR(adap, "Unsupported TCAM type %d\n", mc5->part_type); 3538c2ecf20Sopenharmony_ci err = -EINVAL; 3548c2ecf20Sopenharmony_ci break; 3558c2ecf20Sopenharmony_ci } 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci mc5_dbgi_mode_disable(mc5); 3588c2ecf20Sopenharmony_ci return err; 3598c2ecf20Sopenharmony_ci} 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ci#define MC5_INT_FATAL (F_PARITYERR | F_REQQPARERR | F_DISPQPARERR) 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci/* 3658c2ecf20Sopenharmony_ci * MC5 interrupt handler 3668c2ecf20Sopenharmony_ci */ 3678c2ecf20Sopenharmony_civoid t3_mc5_intr_handler(struct mc5 *mc5) 3688c2ecf20Sopenharmony_ci{ 3698c2ecf20Sopenharmony_ci struct adapter *adap = mc5->adapter; 3708c2ecf20Sopenharmony_ci u32 cause = t3_read_reg(adap, A_MC5_DB_INT_CAUSE); 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ci if ((cause & F_PARITYERR) && mc5->parity_enabled) { 3738c2ecf20Sopenharmony_ci CH_ALERT(adap, "MC5 parity error\n"); 3748c2ecf20Sopenharmony_ci mc5->stats.parity_err++; 3758c2ecf20Sopenharmony_ci } 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_ci if (cause & F_REQQPARERR) { 3788c2ecf20Sopenharmony_ci CH_ALERT(adap, "MC5 request queue parity error\n"); 3798c2ecf20Sopenharmony_ci mc5->stats.reqq_parity_err++; 3808c2ecf20Sopenharmony_ci } 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci if (cause & F_DISPQPARERR) { 3838c2ecf20Sopenharmony_ci CH_ALERT(adap, "MC5 dispatch queue parity error\n"); 3848c2ecf20Sopenharmony_ci mc5->stats.dispq_parity_err++; 3858c2ecf20Sopenharmony_ci } 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci if (cause & F_ACTRGNFULL) 3888c2ecf20Sopenharmony_ci mc5->stats.active_rgn_full++; 3898c2ecf20Sopenharmony_ci if (cause & F_NFASRCHFAIL) 3908c2ecf20Sopenharmony_ci mc5->stats.nfa_srch_err++; 3918c2ecf20Sopenharmony_ci if (cause & F_UNKNOWNCMD) 3928c2ecf20Sopenharmony_ci mc5->stats.unknown_cmd++; 3938c2ecf20Sopenharmony_ci if (cause & F_DELACTEMPTY) 3948c2ecf20Sopenharmony_ci mc5->stats.del_act_empty++; 3958c2ecf20Sopenharmony_ci if (cause & MC5_INT_FATAL) 3968c2ecf20Sopenharmony_ci t3_fatal_err(adap); 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci t3_write_reg(adap, A_MC5_DB_INT_CAUSE, cause); 3998c2ecf20Sopenharmony_ci} 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_civoid t3_mc5_prep(struct adapter *adapter, struct mc5 *mc5, int mode) 4028c2ecf20Sopenharmony_ci{ 4038c2ecf20Sopenharmony_ci#define K * 1024 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_ci static unsigned int tcam_part_size[] = { /* in K 72-bit entries */ 4068c2ecf20Sopenharmony_ci 64 K, 128 K, 256 K, 32 K 4078c2ecf20Sopenharmony_ci }; 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ci#undef K 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci u32 cfg = t3_read_reg(adapter, A_MC5_DB_CONFIG); 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_ci mc5->adapter = adapter; 4148c2ecf20Sopenharmony_ci mc5->mode = (unsigned char)mode; 4158c2ecf20Sopenharmony_ci mc5->part_type = (unsigned char)G_TMTYPE(cfg); 4168c2ecf20Sopenharmony_ci if (cfg & F_TMTYPEHI) 4178c2ecf20Sopenharmony_ci mc5->part_type |= 4; 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci mc5->tcam_size = tcam_part_size[G_TMPARTSIZE(cfg)]; 4208c2ecf20Sopenharmony_ci if (mode == MC5_MODE_144_BIT) 4218c2ecf20Sopenharmony_ci mc5->tcam_size /= 2; 4228c2ecf20Sopenharmony_ci} 423