1/* 2 * Copyright (c) 2005-2009 Brocade Communications Systems, Inc. 3 * All rights reserved 4 * www.brocade.com 5 * 6 * Linux driver for Brocade Fibre Channel Host Bus Adapter. 7 * 8 * This program is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License (GPL) Version 2 as 10 * published by the Free Software Foundation 11 * 12 * This program is distributed in the hope that it will be useful, but 13 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * General Public License for more details. 16 */ 17 18#include <bfa.h> 19#include <bfa_ioc.h> 20#include <bfa_fwimg_priv.h> 21#include <cna/bfa_cna_trcmod.h> 22#include <cs/bfa_debug.h> 23#include <bfi/bfi_ioc.h> 24#include <bfi/bfi_ctreg.h> 25#include <log/bfa_log_hal.h> 26#include <defs/bfa_defs_pci.h> 27 28BFA_TRC_FILE(CNA, IOC_CT); 29 30/* 31 * forward declarations 32 */ 33static bfa_status_t bfa_ioc_ct_pll_init(struct bfa_ioc_s *ioc); 34static bfa_boolean_t bfa_ioc_ct_firmware_lock(struct bfa_ioc_s *ioc); 35static void bfa_ioc_ct_firmware_unlock(struct bfa_ioc_s *ioc); 36static void bfa_ioc_ct_reg_init(struct bfa_ioc_s *ioc); 37static void bfa_ioc_ct_map_port(struct bfa_ioc_s *ioc); 38static void bfa_ioc_ct_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix); 39static void bfa_ioc_ct_notify_hbfail(struct bfa_ioc_s *ioc); 40static void bfa_ioc_ct_ownership_reset(struct bfa_ioc_s *ioc); 41 42struct bfa_ioc_hwif_s hwif_ct; 43 44/** 45 * Called from bfa_ioc_attach() to map asic specific calls. 46 */ 47void 48bfa_ioc_set_ct_hwif(struct bfa_ioc_s *ioc) 49{ 50 hwif_ct.ioc_pll_init = bfa_ioc_ct_pll_init; 51 hwif_ct.ioc_firmware_lock = bfa_ioc_ct_firmware_lock; 52 hwif_ct.ioc_firmware_unlock = bfa_ioc_ct_firmware_unlock; 53 hwif_ct.ioc_reg_init = bfa_ioc_ct_reg_init; 54 hwif_ct.ioc_map_port = bfa_ioc_ct_map_port; 55 hwif_ct.ioc_isr_mode_set = bfa_ioc_ct_isr_mode_set; 56 hwif_ct.ioc_notify_hbfail = bfa_ioc_ct_notify_hbfail; 57 hwif_ct.ioc_ownership_reset = bfa_ioc_ct_ownership_reset; 58 59 ioc->ioc_hwif = &hwif_ct; 60} 61 62/** 63 * Return true if firmware of current driver matches the running firmware. 64 */ 65static bfa_boolean_t 66bfa_ioc_ct_firmware_lock(struct bfa_ioc_s *ioc) 67{ 68 enum bfi_ioc_state ioc_fwstate; 69 u32 usecnt; 70 struct bfi_ioc_image_hdr_s fwhdr; 71 72 /** 73 * Firmware match check is relevant only for CNA. 74 */ 75 if (!ioc->cna) 76 return BFA_TRUE; 77 78 /** 79 * If bios boot (flash based) -- do not increment usage count 80 */ 81 if (bfi_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)) < BFA_IOC_FWIMG_MINSZ) 82 return BFA_TRUE; 83 84 bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg); 85 usecnt = bfa_reg_read(ioc->ioc_regs.ioc_usage_reg); 86 87 /** 88 * If usage count is 0, always return TRUE. 89 */ 90 if (usecnt == 0) { 91 bfa_reg_write(ioc->ioc_regs.ioc_usage_reg, 1); 92 bfa_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg); 93 bfa_trc(ioc, usecnt); 94 return BFA_TRUE; 95 } 96 97 ioc_fwstate = bfa_reg_read(ioc->ioc_regs.ioc_fwstate); 98 bfa_trc(ioc, ioc_fwstate); 99 100 /** 101 * Use count cannot be non-zero and chip in uninitialized state. 102 */ 103 bfa_assert(ioc_fwstate != BFI_IOC_UNINIT); 104 105 /** 106 * Check if another driver with a different firmware is active 107 */ 108 bfa_ioc_fwver_get(ioc, &fwhdr); 109 if (!bfa_ioc_fwver_cmp(ioc, &fwhdr)) { 110 bfa_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg); 111 bfa_trc(ioc, usecnt); 112 return BFA_FALSE; 113 } 114 115 /** 116 * Same firmware version. Increment the reference count. 117 */ 118 usecnt++; 119 bfa_reg_write(ioc->ioc_regs.ioc_usage_reg, usecnt); 120 bfa_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg); 121 bfa_trc(ioc, usecnt); 122 return BFA_TRUE; 123} 124 125static void 126bfa_ioc_ct_firmware_unlock(struct bfa_ioc_s *ioc) 127{ 128 u32 usecnt; 129 130 /** 131 * Firmware lock is relevant only for CNA. 132 */ 133 if (!ioc->cna) 134 return; 135 136 /** 137 * If bios boot (flash based) -- do not decrement usage count 138 */ 139 if (bfi_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)) < BFA_IOC_FWIMG_MINSZ) 140 return; 141 142 /** 143 * decrement usage count 144 */ 145 bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg); 146 usecnt = bfa_reg_read(ioc->ioc_regs.ioc_usage_reg); 147 bfa_assert(usecnt > 0); 148 149 usecnt--; 150 bfa_reg_write(ioc->ioc_regs.ioc_usage_reg, usecnt); 151 bfa_trc(ioc, usecnt); 152 153 bfa_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg); 154} 155 156/** 157 * Notify other functions on HB failure. 158 */ 159static void 160bfa_ioc_ct_notify_hbfail(struct bfa_ioc_s *ioc) 161{ 162 if (ioc->cna) { 163 bfa_reg_write(ioc->ioc_regs.ll_halt, __FW_INIT_HALT_P); 164 /* Wait for halt to take effect */ 165 bfa_reg_read(ioc->ioc_regs.ll_halt); 166 } else { 167 bfa_reg_write(ioc->ioc_regs.err_set, __PSS_ERR_STATUS_SET); 168 bfa_reg_read(ioc->ioc_regs.err_set); 169 } 170} 171 172/** 173 * Host to LPU mailbox message addresses 174 */ 175static struct { u32 hfn_mbox, lpu_mbox, hfn_pgn; } iocreg_fnreg[] = { 176 { HOSTFN0_LPU_MBOX0_0, LPU_HOSTFN0_MBOX0_0, HOST_PAGE_NUM_FN0 }, 177 { HOSTFN1_LPU_MBOX0_8, LPU_HOSTFN1_MBOX0_8, HOST_PAGE_NUM_FN1 }, 178 { HOSTFN2_LPU_MBOX0_0, LPU_HOSTFN2_MBOX0_0, HOST_PAGE_NUM_FN2 }, 179 { HOSTFN3_LPU_MBOX0_8, LPU_HOSTFN3_MBOX0_8, HOST_PAGE_NUM_FN3 } 180}; 181 182/** 183 * Host <-> LPU mailbox command/status registers - port 0 184 */ 185static struct { u32 hfn, lpu; } iocreg_mbcmd_p0[] = { 186 { HOSTFN0_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN0_MBOX0_CMD_STAT }, 187 { HOSTFN1_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN1_MBOX0_CMD_STAT }, 188 { HOSTFN2_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN2_MBOX0_CMD_STAT }, 189 { HOSTFN3_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN3_MBOX0_CMD_STAT } 190}; 191 192/** 193 * Host <-> LPU mailbox command/status registers - port 1 194 */ 195static struct { u32 hfn, lpu; } iocreg_mbcmd_p1[] = { 196 { HOSTFN0_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN0_MBOX0_CMD_STAT }, 197 { HOSTFN1_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN1_MBOX0_CMD_STAT }, 198 { HOSTFN2_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN2_MBOX0_CMD_STAT }, 199 { HOSTFN3_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN3_MBOX0_CMD_STAT } 200}; 201 202static void 203bfa_ioc_ct_reg_init(struct bfa_ioc_s *ioc) 204{ 205 bfa_os_addr_t rb; 206 int pcifn = bfa_ioc_pcifn(ioc); 207 208 rb = bfa_ioc_bar0(ioc); 209 210 ioc->ioc_regs.hfn_mbox = rb + iocreg_fnreg[pcifn].hfn_mbox; 211 ioc->ioc_regs.lpu_mbox = rb + iocreg_fnreg[pcifn].lpu_mbox; 212 ioc->ioc_regs.host_page_num_fn = rb + iocreg_fnreg[pcifn].hfn_pgn; 213 214 if (ioc->port_id == 0) { 215 ioc->ioc_regs.heartbeat = rb + BFA_IOC0_HBEAT_REG; 216 ioc->ioc_regs.ioc_fwstate = rb + BFA_IOC0_STATE_REG; 217 ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd_p0[pcifn].hfn; 218 ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd_p0[pcifn].lpu; 219 ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P0; 220 } else { 221 ioc->ioc_regs.heartbeat = (rb + BFA_IOC1_HBEAT_REG); 222 ioc->ioc_regs.ioc_fwstate = (rb + BFA_IOC1_STATE_REG); 223 ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd_p1[pcifn].hfn; 224 ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd_p1[pcifn].lpu; 225 ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P1; 226 } 227 228 /* 229 * PSS control registers 230 */ 231 ioc->ioc_regs.pss_ctl_reg = (rb + PSS_CTL_REG); 232 ioc->ioc_regs.pss_err_status_reg = (rb + PSS_ERR_STATUS_REG); 233 ioc->ioc_regs.app_pll_fast_ctl_reg = (rb + APP_PLL_425_CTL_REG); 234 ioc->ioc_regs.app_pll_slow_ctl_reg = (rb + APP_PLL_312_CTL_REG); 235 236 /* 237 * IOC semaphore registers and serialization 238 */ 239 ioc->ioc_regs.ioc_sem_reg = (rb + HOST_SEM0_REG); 240 ioc->ioc_regs.ioc_usage_sem_reg = (rb + HOST_SEM1_REG); 241 ioc->ioc_regs.ioc_init_sem_reg = (rb + HOST_SEM2_REG); 242 ioc->ioc_regs.ioc_usage_reg = (rb + BFA_FW_USE_COUNT); 243 244 /** 245 * sram memory access 246 */ 247 ioc->ioc_regs.smem_page_start = (rb + PSS_SMEM_PAGE_START); 248 ioc->ioc_regs.smem_pg0 = BFI_IOC_SMEM_PG0_CT; 249 250 /* 251 * err set reg : for notification of hb failure in fcmode 252 */ 253 ioc->ioc_regs.err_set = (rb + ERR_SET_REG); 254} 255 256/** 257 * Initialize IOC to port mapping. 258 */ 259 260#define FNC_PERS_FN_SHIFT(__fn) ((__fn) * 8) 261static void 262bfa_ioc_ct_map_port(struct bfa_ioc_s *ioc) 263{ 264 bfa_os_addr_t rb = ioc->pcidev.pci_bar_kva; 265 u32 r32; 266 267 /** 268 * For catapult, base port id on personality register and IOC type 269 */ 270 r32 = bfa_reg_read(rb + FNC_PERS_REG); 271 r32 >>= FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc)); 272 ioc->port_id = (r32 & __F0_PORT_MAP_MK) >> __F0_PORT_MAP_SH; 273 274 bfa_trc(ioc, bfa_ioc_pcifn(ioc)); 275 bfa_trc(ioc, ioc->port_id); 276} 277 278/** 279 * Set interrupt mode for a function: INTX or MSIX 280 */ 281static void 282bfa_ioc_ct_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix) 283{ 284 bfa_os_addr_t rb = ioc->pcidev.pci_bar_kva; 285 u32 r32, mode; 286 287 r32 = bfa_reg_read(rb + FNC_PERS_REG); 288 bfa_trc(ioc, r32); 289 290 mode = (r32 >> FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc))) & 291 __F0_INTX_STATUS; 292 293 /** 294 * If already in desired mode, do not change anything 295 */ 296 if (!msix && mode) 297 return; 298 299 if (msix) 300 mode = __F0_INTX_STATUS_MSIX; 301 else 302 mode = __F0_INTX_STATUS_INTA; 303 304 r32 &= ~(__F0_INTX_STATUS << FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc))); 305 r32 |= (mode << FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc))); 306 bfa_trc(ioc, r32); 307 308 bfa_reg_write(rb + FNC_PERS_REG, r32); 309} 310 311static bfa_status_t 312bfa_ioc_ct_pll_init(struct bfa_ioc_s *ioc) 313{ 314 bfa_os_addr_t rb = ioc->pcidev.pci_bar_kva; 315 u32 pll_sclk, pll_fclk, r32; 316 317 /* 318 * Hold semaphore so that nobody can access the chip during init. 319 */ 320 bfa_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg); 321 322 pll_sclk = __APP_PLL_312_LRESETN | __APP_PLL_312_ENARST | 323 __APP_PLL_312_RSEL200500 | __APP_PLL_312_P0_1(3U) | 324 __APP_PLL_312_JITLMT0_1(3U) | 325 __APP_PLL_312_CNTLMT0_1(1U); 326 pll_fclk = __APP_PLL_425_LRESETN | __APP_PLL_425_ENARST | 327 __APP_PLL_425_RSEL200500 | __APP_PLL_425_P0_1(3U) | 328 __APP_PLL_425_JITLMT0_1(3U) | 329 __APP_PLL_425_CNTLMT0_1(1U); 330 331 /** 332 * For catapult, choose operational mode FC/FCoE 333 */ 334 if (ioc->fcmode) { 335 bfa_reg_write((rb + OP_MODE), 0); 336 bfa_reg_write((rb + ETH_MAC_SER_REG), 337 __APP_EMS_CMLCKSEL | 338 __APP_EMS_REFCKBUFEN2 | 339 __APP_EMS_CHANNEL_SEL); 340 } else { 341 ioc->pllinit = BFA_TRUE; 342 bfa_reg_write((rb + OP_MODE), __GLOBAL_FCOE_MODE); 343 bfa_reg_write((rb + ETH_MAC_SER_REG), 344 __APP_EMS_REFCKBUFEN1); 345 } 346 347 bfa_reg_write((rb + BFA_IOC0_STATE_REG), BFI_IOC_UNINIT); 348 bfa_reg_write((rb + BFA_IOC1_STATE_REG), BFI_IOC_UNINIT); 349 350 bfa_reg_write((rb + HOSTFN0_INT_MSK), 0xffffffffU); 351 bfa_reg_write((rb + HOSTFN1_INT_MSK), 0xffffffffU); 352 bfa_reg_write((rb + HOSTFN0_INT_STATUS), 0xffffffffU); 353 bfa_reg_write((rb + HOSTFN1_INT_STATUS), 0xffffffffU); 354 bfa_reg_write((rb + HOSTFN0_INT_MSK), 0xffffffffU); 355 bfa_reg_write((rb + HOSTFN1_INT_MSK), 0xffffffffU); 356 357 bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg, pll_sclk | 358 __APP_PLL_312_LOGIC_SOFT_RESET); 359 bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg, pll_fclk | 360 __APP_PLL_425_LOGIC_SOFT_RESET); 361 bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg, pll_sclk | 362 __APP_PLL_312_LOGIC_SOFT_RESET | __APP_PLL_312_ENABLE); 363 bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg, pll_fclk | 364 __APP_PLL_425_LOGIC_SOFT_RESET | __APP_PLL_425_ENABLE); 365 366 /** 367 * Wait for PLLs to lock. 368 */ 369 bfa_reg_read(rb + HOSTFN0_INT_MSK); 370 bfa_os_udelay(2000); 371 bfa_reg_write((rb + HOSTFN0_INT_STATUS), 0xffffffffU); 372 bfa_reg_write((rb + HOSTFN1_INT_STATUS), 0xffffffffU); 373 374 bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg, pll_sclk | 375 __APP_PLL_312_ENABLE); 376 bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg, pll_fclk | 377 __APP_PLL_425_ENABLE); 378 379 /** 380 * PSS memory reset is asserted at power-on-reset. Need to clear 381 * this before running EDRAM BISTR 382 */ 383 if (ioc->cna) { 384 bfa_reg_write((rb + PMM_1T_RESET_REG_P0), __PMM_1T_RESET_P); 385 bfa_reg_write((rb + PMM_1T_RESET_REG_P1), __PMM_1T_RESET_P); 386 } 387 388 r32 = bfa_reg_read((rb + PSS_CTL_REG)); 389 r32 &= ~__PSS_LMEM_RESET; 390 bfa_reg_write((rb + PSS_CTL_REG), r32); 391 bfa_os_udelay(1000); 392 393 if (ioc->cna) { 394 bfa_reg_write((rb + PMM_1T_RESET_REG_P0), 0); 395 bfa_reg_write((rb + PMM_1T_RESET_REG_P1), 0); 396 } 397 398 bfa_reg_write((rb + MBIST_CTL_REG), __EDRAM_BISTR_START); 399 bfa_os_udelay(1000); 400 r32 = bfa_reg_read((rb + MBIST_STAT_REG)); 401 bfa_trc(ioc, r32); 402 403 /** 404 * Clear BISTR 405 */ 406 bfa_reg_write((rb + MBIST_CTL_REG), 0); 407 408 /* 409 * release semaphore. 410 */ 411 bfa_ioc_sem_release(ioc->ioc_regs.ioc_init_sem_reg); 412 413 return BFA_STATUS_OK; 414} 415 416/** 417 * Cleanup hw semaphore and usecnt registers 418 */ 419static void 420bfa_ioc_ct_ownership_reset(struct bfa_ioc_s *ioc) 421{ 422 423 if (ioc->cna) { 424 bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg); 425 bfa_reg_write(ioc->ioc_regs.ioc_usage_reg, 0); 426 bfa_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg); 427 } 428 429 /* 430 * Read the hw sem reg to make sure that it is locked 431 * before we clear it. If it is not locked, writing 1 432 * will lock it instead of clearing it. 433 */ 434 bfa_reg_read(ioc->ioc_regs.ioc_sem_reg); 435 bfa_ioc_hw_sem_release(ioc); 436} 437