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_cbreg.h> 25#include <log/bfa_log_hal.h> 26#include <defs/bfa_defs_pci.h> 27 28BFA_TRC_FILE(CNA, IOC_CB); 29 30/* 31 * forward declarations 32 */ 33static bfa_status_t bfa_ioc_cb_pll_init(struct bfa_ioc_s *ioc); 34static bfa_boolean_t bfa_ioc_cb_firmware_lock(struct bfa_ioc_s *ioc); 35static void bfa_ioc_cb_firmware_unlock(struct bfa_ioc_s *ioc); 36static void bfa_ioc_cb_reg_init(struct bfa_ioc_s *ioc); 37static void bfa_ioc_cb_map_port(struct bfa_ioc_s *ioc); 38static void bfa_ioc_cb_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix); 39static void bfa_ioc_cb_notify_hbfail(struct bfa_ioc_s *ioc); 40static void bfa_ioc_cb_ownership_reset(struct bfa_ioc_s *ioc); 41 42struct bfa_ioc_hwif_s hwif_cb; 43 44/** 45 * Called from bfa_ioc_attach() to map asic specific calls. 46 */ 47void 48bfa_ioc_set_cb_hwif(struct bfa_ioc_s *ioc) 49{ 50 hwif_cb.ioc_pll_init = bfa_ioc_cb_pll_init; 51 hwif_cb.ioc_firmware_lock = bfa_ioc_cb_firmware_lock; 52 hwif_cb.ioc_firmware_unlock = bfa_ioc_cb_firmware_unlock; 53 hwif_cb.ioc_reg_init = bfa_ioc_cb_reg_init; 54 hwif_cb.ioc_map_port = bfa_ioc_cb_map_port; 55 hwif_cb.ioc_isr_mode_set = bfa_ioc_cb_isr_mode_set; 56 hwif_cb.ioc_notify_hbfail = bfa_ioc_cb_notify_hbfail; 57 hwif_cb.ioc_ownership_reset = bfa_ioc_cb_ownership_reset; 58 59 ioc->ioc_hwif = &hwif_cb; 60} 61 62/** 63 * Return true if firmware of current driver matches the running firmware. 64 */ 65static bfa_boolean_t 66bfa_ioc_cb_firmware_lock(struct bfa_ioc_s *ioc) 67{ 68 return BFA_TRUE; 69} 70 71static void 72bfa_ioc_cb_firmware_unlock(struct bfa_ioc_s *ioc) 73{ 74} 75 76/** 77 * Notify other functions on HB failure. 78 */ 79static void 80bfa_ioc_cb_notify_hbfail(struct bfa_ioc_s *ioc) 81{ 82 bfa_reg_write(ioc->ioc_regs.err_set, __PSS_ERR_STATUS_SET); 83 bfa_reg_read(ioc->ioc_regs.err_set); 84} 85 86/** 87 * Host to LPU mailbox message addresses 88 */ 89static struct { u32 hfn_mbox, lpu_mbox, hfn_pgn; } iocreg_fnreg[] = { 90 { HOSTFN0_LPU_MBOX0_0, LPU_HOSTFN0_MBOX0_0, HOST_PAGE_NUM_FN0 }, 91 { HOSTFN1_LPU_MBOX0_8, LPU_HOSTFN1_MBOX0_8, HOST_PAGE_NUM_FN1 } 92}; 93 94/** 95 * Host <-> LPU mailbox command/status registers 96 */ 97static struct { u32 hfn, lpu; } iocreg_mbcmd[] = { 98 { HOSTFN0_LPU0_CMD_STAT, LPU0_HOSTFN0_CMD_STAT }, 99 { HOSTFN1_LPU1_CMD_STAT, LPU1_HOSTFN1_CMD_STAT } 100}; 101 102static void 103bfa_ioc_cb_reg_init(struct bfa_ioc_s *ioc) 104{ 105 bfa_os_addr_t rb; 106 int pcifn = bfa_ioc_pcifn(ioc); 107 108 rb = bfa_ioc_bar0(ioc); 109 110 ioc->ioc_regs.hfn_mbox = rb + iocreg_fnreg[pcifn].hfn_mbox; 111 ioc->ioc_regs.lpu_mbox = rb + iocreg_fnreg[pcifn].lpu_mbox; 112 ioc->ioc_regs.host_page_num_fn = rb + iocreg_fnreg[pcifn].hfn_pgn; 113 114 if (ioc->port_id == 0) { 115 ioc->ioc_regs.heartbeat = rb + BFA_IOC0_HBEAT_REG; 116 ioc->ioc_regs.ioc_fwstate = rb + BFA_IOC0_STATE_REG; 117 } else { 118 ioc->ioc_regs.heartbeat = (rb + BFA_IOC1_HBEAT_REG); 119 ioc->ioc_regs.ioc_fwstate = (rb + BFA_IOC1_STATE_REG); 120 } 121 122 /** 123 * Host <-> LPU mailbox command/status registers 124 */ 125 ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd[pcifn].hfn; 126 ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd[pcifn].lpu; 127 128 /* 129 * PSS control registers 130 */ 131 ioc->ioc_regs.pss_ctl_reg = (rb + PSS_CTL_REG); 132 ioc->ioc_regs.pss_err_status_reg = (rb + PSS_ERR_STATUS_REG); 133 ioc->ioc_regs.app_pll_fast_ctl_reg = (rb + APP_PLL_400_CTL_REG); 134 ioc->ioc_regs.app_pll_slow_ctl_reg = (rb + APP_PLL_212_CTL_REG); 135 136 /* 137 * IOC semaphore registers and serialization 138 */ 139 ioc->ioc_regs.ioc_sem_reg = (rb + HOST_SEM0_REG); 140 ioc->ioc_regs.ioc_init_sem_reg = (rb + HOST_SEM2_REG); 141 142 /** 143 * sram memory access 144 */ 145 ioc->ioc_regs.smem_page_start = (rb + PSS_SMEM_PAGE_START); 146 ioc->ioc_regs.smem_pg0 = BFI_IOC_SMEM_PG0_CB; 147 148 /* 149 * err set reg : for notification of hb failure 150 */ 151 ioc->ioc_regs.err_set = (rb + ERR_SET_REG); 152} 153 154/** 155 * Initialize IOC to port mapping. 156 */ 157static void 158bfa_ioc_cb_map_port(struct bfa_ioc_s *ioc) 159{ 160 /** 161 * For crossbow, port id is same as pci function. 162 */ 163 ioc->port_id = bfa_ioc_pcifn(ioc); 164 bfa_trc(ioc, ioc->port_id); 165} 166 167/** 168 * Set interrupt mode for a function: INTX or MSIX 169 */ 170static void 171bfa_ioc_cb_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix) 172{ 173} 174 175static bfa_status_t 176bfa_ioc_cb_pll_init(struct bfa_ioc_s *ioc) 177{ 178 bfa_os_addr_t rb = ioc->pcidev.pci_bar_kva; 179 u32 pll_sclk, pll_fclk; 180 181 /* 182 * Hold semaphore so that nobody can access the chip during init. 183 */ 184 bfa_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg); 185 186 pll_sclk = __APP_PLL_212_ENABLE | __APP_PLL_212_LRESETN | 187 __APP_PLL_212_P0_1(3U) | 188 __APP_PLL_212_JITLMT0_1(3U) | 189 __APP_PLL_212_CNTLMT0_1(3U); 190 pll_fclk = __APP_PLL_400_ENABLE | __APP_PLL_400_LRESETN | 191 __APP_PLL_400_RSEL200500 | __APP_PLL_400_P0_1(3U) | 192 __APP_PLL_400_JITLMT0_1(3U) | 193 __APP_PLL_400_CNTLMT0_1(3U); 194 195 bfa_reg_write((rb + BFA_IOC0_STATE_REG), BFI_IOC_UNINIT); 196 bfa_reg_write((rb + BFA_IOC1_STATE_REG), BFI_IOC_UNINIT); 197 198 bfa_reg_write((rb + HOSTFN0_INT_MSK), 0xffffffffU); 199 bfa_reg_write((rb + HOSTFN1_INT_MSK), 0xffffffffU); 200 bfa_reg_write((rb + HOSTFN0_INT_STATUS), 0xffffffffU); 201 bfa_reg_write((rb + HOSTFN1_INT_STATUS), 0xffffffffU); 202 bfa_reg_write((rb + HOSTFN0_INT_MSK), 0xffffffffU); 203 bfa_reg_write((rb + HOSTFN1_INT_MSK), 0xffffffffU); 204 205 bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg, 206 __APP_PLL_212_LOGIC_SOFT_RESET); 207 bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg, 208 __APP_PLL_212_BYPASS | 209 __APP_PLL_212_LOGIC_SOFT_RESET); 210 bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg, 211 __APP_PLL_400_LOGIC_SOFT_RESET); 212 bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg, 213 __APP_PLL_400_BYPASS | 214 __APP_PLL_400_LOGIC_SOFT_RESET); 215 bfa_os_udelay(2); 216 bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg, 217 __APP_PLL_212_LOGIC_SOFT_RESET); 218 bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg, 219 __APP_PLL_400_LOGIC_SOFT_RESET); 220 221 bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg, 222 pll_sclk | __APP_PLL_212_LOGIC_SOFT_RESET); 223 bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg, 224 pll_fclk | __APP_PLL_400_LOGIC_SOFT_RESET); 225 226 /** 227 * Wait for PLLs to lock. 228 */ 229 bfa_os_udelay(2000); 230 bfa_reg_write((rb + HOSTFN0_INT_STATUS), 0xffffffffU); 231 bfa_reg_write((rb + HOSTFN1_INT_STATUS), 0xffffffffU); 232 233 bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg, pll_sclk); 234 bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg, pll_fclk); 235 236 /* 237 * release semaphore. 238 */ 239 bfa_ioc_sem_release(ioc->ioc_regs.ioc_init_sem_reg); 240 241 return BFA_STATUS_OK; 242} 243 244/** 245 * Cleanup hw semaphore and usecnt registers 246 */ 247static void 248bfa_ioc_cb_ownership_reset(struct bfa_ioc_s *ioc) 249{ 250 251 /* 252 * Read the hw sem reg to make sure that it is locked 253 * before we clear it. If it is not locked, writing 1 254 * will lock it instead of clearing it. 255 */ 256 bfa_reg_read(ioc->ioc_regs.ioc_sem_reg); 257 bfa_ioc_hw_sem_release(ioc); 258} 259