1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * This file is part of the Chelsio T1 Ethernet driver. 24 * 25 * Copyright (C) 2003-2005 Chelsio Communications. All rights reserved. 26 */ 27 28 #include "common.h" 29 #include "regs.h" 30 #include "mc4.h" 31 32 struct pemc4 { 33 adapter_t *adapter; 34 unsigned int size; 35 unsigned int nwords; /* MC4 width in terms of 32-bit words */ 36 struct pemc4_intr_counts intr_cnt; 37 }; 38 39 void t1_mc4_destroy(struct pemc4 *mc4) 40 { 41 t1_os_free((void *)mc4, sizeof(*mc4)); 42 } 43 44 #define is_MC4A(adapter) (!t1_is_T1B(adapter)) 45 46 /* Calculate amount of MC4 memory. */ 47 static unsigned int __devinit mc4_calc_size(adapter_t *adapter) 48 { 49 u32 mc4_cfg = t1_read_reg_4(adapter, A_MC4_CFG); 50 unsigned int width = is_MC4A(adapter) ? G_MC4A_WIDTH(mc4_cfg) : 51 !!(mc4_cfg & F_MC4_NARROW); 52 53 return (256 * 1024 * 1024) >> width; 54 } 55 56 /* 57 * Write a value to a register and check that the write completed. These 58 * writes normally complete in a cycle or two, so one read should suffice but 59 * just in case we give them a bit of grace period. Note that the very first 60 * read exists to flush the posted write to the device. 61 */ 62 static int wrreg_wait(adapter_t *adapter, unsigned int addr, u32 val) 63 { 64 int attempts = 2; 65 66 t1_write_reg_4(adapter, addr, val); 67 val = t1_read_reg_4(adapter, addr); /* flush */ 68 while (attempts--) { 69 if (!(t1_read_reg_4(adapter, addr) & F_BUSY)) 70 return 0; 71 if (attempts) 72 DELAY_US(1); 73 } 74 CH_ERR("%s: write to MC4 register 0x%x timed out\n", 75 adapter_name(adapter), addr); 76 return -EIO; 77 } 78 79 #define MC4_DLL_DONE (F_MASTER_DLL_LOCKED | F_MASTER_DLL_MAX_TAP_COUNT) 80 81 int t1_mc4_init(struct pemc4 *mc4, unsigned int mc4_clock) 82 { 83 int attempts; 84 u32 val; 85 unsigned int width, ext_mode, slow_mode; 86 adapter_t *adapter = mc4->adapter; 87 88 /* Power up the FCRAMs. */ 89 val = t1_read_reg_4(adapter, A_MC4_CFG); 90 t1_write_reg_4(adapter, A_MC4_CFG, val | F_POWER_UP); 91 val = t1_read_reg_4(adapter, A_MC4_CFG); /* flush */ 92 93 if (is_MC4A(adapter)) { 94 slow_mode = val & F_MC4A_SLOW; 95 width = G_MC4A_WIDTH(val); 96 97 /* If we're not in slow mode, we are using the DLLs */ 98 if (!slow_mode) { 99 /* Clear Reset */ 100 val = t1_read_reg_4(adapter, A_MC4_STROBE); 101 t1_write_reg_4(adapter, A_MC4_STROBE, 102 val & ~F_SLAVE_DLL_RESET); 103 104 /* Wait for slave DLLs to lock */ 105 DELAY_US(2 * 512 / (mc4_clock / 1000000) + 1); 106 } 107 } else { 108 slow_mode = val & F_MC4_SLOW; 109 width = !!(val & F_MC4_NARROW); 110 111 /* Initializes the master DLL and slave delay lines. */ 112 if (t1_is_asic(adapter) && !slow_mode) { 113 val = t1_read_reg_4(adapter, A_MC4_STROBE); 114 t1_write_reg_4(adapter, A_MC4_STROBE, 115 val & ~F_MASTER_DLL_RESET); 116 117 /* Wait for the master DLL to lock. */ 118 attempts = 100; 119 do { 120 DELAY_US(1); 121 val = t1_read_reg_4(adapter, A_MC4_STROBE); 122 } while (!(val & MC4_DLL_DONE) && --attempts); 123 if (!(val & MC4_DLL_DONE)) { 124 CH_ERR("%s: MC4 DLL lock failed\n", 125 adapter_name(adapter)); 126 goto out_fail; 127 } 128 } 129 } 130 131 mc4->nwords = 4 >> width; 132 133 /* Set the FCRAM output drive strength and enable DLLs if needed */ 134 ext_mode = t1_is_asic(adapter) && !slow_mode ? 0 : 1; 135 if (wrreg_wait(adapter, A_MC4_EXT_MODE, ext_mode)) 136 goto out_fail; 137 138 /* Specify the FCRAM operating parameters */ 139 if (wrreg_wait(adapter, A_MC4_MODE, 0x32)) 140 goto out_fail; 141 142 /* Initiate an immediate refresh and wait for the write to complete. */ 143 val = t1_read_reg_4(adapter, A_MC4_REFRESH); 144 if (wrreg_wait(adapter, A_MC4_REFRESH, val & ~F_REFRESH_ENABLE)) 145 goto out_fail; 146 147 /* 2nd immediate refresh as before */ 148 if (wrreg_wait(adapter, A_MC4_REFRESH, val & ~F_REFRESH_ENABLE)) 149 goto out_fail; 150 151 /* Convert to KHz first to avoid 64-bit division. */ 152 mc4_clock /= 1000; /* Hz->KHz */ 153 mc4_clock = mc4_clock * 7812 + mc4_clock / 2; /* ns */ 154 mc4_clock /= 1000000; /* KHz->MHz, ns->us */ 155 156 /* Enable periodic refresh. */ 157 t1_write_reg_4(adapter, A_MC4_REFRESH, 158 F_REFRESH_ENABLE | V_REFRESH_DIVISOR(mc4_clock)); 159 (void) t1_read_reg_4(adapter, A_MC4_REFRESH); /* flush */ 160 161 t1_write_reg_4(adapter, A_MC4_ECC_CNTL, 162 F_ECC_GENERATION_ENABLE | F_ECC_CHECK_ENABLE); 163 164 /* Use the BIST engine to clear all of the MC4 memory. */ 165 t1_write_reg_4(adapter, A_MC4_BIST_ADDR_BEG, 0); 166 t1_write_reg_4(adapter, A_MC4_BIST_ADDR_END, (mc4->size << width) - 1); 167 t1_write_reg_4(adapter, A_MC4_BIST_DATA, 0); 168 t1_write_reg_4(adapter, A_MC4_BIST_OP, V_OP(1) | 0x1f0); 169 (void) t1_read_reg_4(adapter, A_MC4_BIST_OP); /* flush */ 170 171 attempts = 100; 172 do { 173 DELAY_MS(100); 174 val = t1_read_reg_4(adapter, A_MC4_BIST_OP); 175 } while ((val & F_BUSY) && --attempts); 176 if (val & F_BUSY) { 177 CH_ERR("%s: MC4 BIST timed out\n", adapter_name(adapter)); 178 goto out_fail; 179 } 180 181 /* Enable normal memory accesses. */ 182 val = t1_read_reg_4(adapter, A_MC4_CFG); 183 t1_write_reg_4(adapter, A_MC4_CFG, val | F_READY); 184 val = t1_read_reg_4(adapter, A_MC4_CFG); /* flush */ 185 return 0; 186 187 out_fail: 188 return -1; 189 } 190 191 struct pemc4 * __devinit t1_mc4_create(adapter_t *adapter) 192 { 193 struct pemc4 *mc4 = t1_os_malloc_wait_zero(sizeof(*mc4)); 194 195 if (mc4) { 196 mc4->adapter = adapter; 197 mc4->size = mc4_calc_size(adapter); 198 } 199 return mc4; 200 } 201 202 unsigned int t1_mc4_get_size(struct pemc4 *mc4) 203 { 204 return mc4->size; 205 } 206 207 #define MC4_INT_MASK (F_MC4_CORR_ERR | F_MC4_UNCORR_ERR | F_MC4_ADDR_ERR) 208 #define MC4_INT_FATAL (F_MC4_UNCORR_ERR | F_MC4_ADDR_ERR) 209 210 void t1_mc4_intr_enable(struct pemc4 *mc4) 211 { 212 u32 pl_intr; 213 214 if (t1_is_asic(mc4->adapter)) { 215 t1_write_reg_4(mc4->adapter, A_MC4_INT_ENABLE, MC4_INT_MASK); 216 217 pl_intr = t1_read_reg_4(mc4->adapter, A_PL_ENABLE); 218 t1_write_reg_4(mc4->adapter, A_PL_ENABLE, 219 pl_intr | F_PL_INTR_MC4); 220 } 221 } 222 223 void t1_mc4_intr_disable(struct pemc4 *mc4) 224 { 225 u32 pl_intr; 226 227 if (t1_is_asic(mc4->adapter)) { 228 t1_write_reg_4(mc4->adapter, A_MC4_INT_ENABLE, 0); 229 230 pl_intr = t1_read_reg_4(mc4->adapter, A_PL_ENABLE); 231 t1_write_reg_4(mc4->adapter, A_PL_ENABLE, 232 pl_intr & ~F_PL_INTR_MC4); 233 } 234 } 235 236 void t1_mc4_intr_clear(struct pemc4 *mc4) 237 { 238 if (t1_is_asic(mc4->adapter)) { 239 t1_write_reg_4(mc4->adapter, A_MC4_INT_CAUSE, 0xffffffff); 240 t1_write_reg_4(mc4->adapter, A_PL_CAUSE, F_PL_INTR_MC4); 241 } 242 } 243 244 int t1_mc4_intr_handler(struct pemc4 *mc4) 245 { 246 adapter_t *adapter = mc4->adapter; 247 u32 cause = t1_read_reg_4(adapter, A_MC4_INT_CAUSE); 248 249 if (cause & F_MC4_CORR_ERR) { 250 mc4->intr_cnt.corr_err++; 251 CH_WARN("%s: MC4 correctable error at addr 0x%x, " 252 "data 0x%x 0x%x 0x%x 0x%x 0x%x\n", 253 adapter_name(adapter), 254 G_MC4_CE_ADDR(t1_read_reg_4(adapter, A_MC4_CE_ADDR)), 255 t1_read_reg_4(adapter, A_MC4_CE_DATA0), 256 t1_read_reg_4(adapter, A_MC4_CE_DATA1), 257 t1_read_reg_4(adapter, A_MC4_CE_DATA2), 258 t1_read_reg_4(adapter, A_MC4_CE_DATA3), 259 t1_read_reg_4(adapter, A_MC4_CE_DATA4)); 260 } 261 262 if (cause & F_MC4_UNCORR_ERR) { 263 mc4->intr_cnt.uncorr_err++; 264 CH_ALERT("%s: MC4 uncorrectable error at addr 0x%x, " 265 "data 0x%x 0x%x 0x%x 0x%x 0x%x\n", 266 adapter_name(adapter), 267 G_MC4_UE_ADDR(t1_read_reg_4(adapter, A_MC4_UE_ADDR)), 268 t1_read_reg_4(adapter, A_MC4_UE_DATA0), 269 t1_read_reg_4(adapter, A_MC4_UE_DATA1), 270 t1_read_reg_4(adapter, A_MC4_UE_DATA2), 271 t1_read_reg_4(adapter, A_MC4_UE_DATA3), 272 t1_read_reg_4(adapter, A_MC4_UE_DATA4)); 273 } 274 275 if (cause & F_MC4_ADDR_ERR) { 276 mc4->intr_cnt.addr_err++; 277 CH_ALERT("%s: MC4 address error\n", adapter_name(adapter)); 278 } 279 280 if (cause & MC4_INT_FATAL) 281 t1_fatal_err(adapter); 282 283 t1_write_reg_4(mc4->adapter, A_MC4_INT_CAUSE, cause); 284 return 0; 285 } 286 287 const struct pemc4_intr_counts *t1_mc4_get_intr_counts(struct pemc4 *mc4) 288 { 289 return &mc4->intr_cnt; 290 } 291 292 /* 293 * Read n 256-bit words from MC4 starting at word start, using backdoor 294 * accesses. 295 */ 296 int t1_mc4_bd_read(struct pemc4 *mc4, unsigned int start, unsigned int n, 297 u32 *buf) 298 { 299 adapter_t *adap = mc4->adapter; 300 unsigned int size256 = mc4->size / 32, c = 8 / mc4->nwords, i; 301 302 if (start >= size256 || start + n > size256) 303 return -EINVAL; 304 305 for (i = 8, start *= 16 * c, n *= c; n; --n, start += 16) { 306 int attempts = 10; 307 u32 val; 308 309 t1_write_reg_4(adap, A_MC4_BD_ADDR, start); 310 t1_write_reg_4(adap, A_MC4_BD_OP, 0); 311 val = t1_read_reg_4(adap, A_MC4_BD_OP); 312 while ((val & F_BUSY) && attempts--) 313 val = t1_read_reg_4(adap, A_MC4_BD_OP); 314 315 if (val & F_BUSY) 316 return -EIO; 317 318 buf[--i] = t1_read_reg_4(adap, A_MC4_BD_DATA3); 319 if (mc4->nwords >= 2) 320 buf[--i] = t1_read_reg_4(adap, A_MC4_BD_DATA2); 321 if (mc4->nwords == 4) { 322 buf[--i] = t1_read_reg_4(adap, A_MC4_BD_DATA1); 323 buf[--i] = t1_read_reg_4(adap, A_MC4_BD_DATA0); 324 } 325 if (i == 0) { 326 i = 8; 327 buf += 8; 328 } 329 } 330 return 0; 331 } 332