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