1 /* 2 * Copyright (c) 2005-2010 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 "bfad_drv.h" 19 #include "bfa_ioc.h" 20 #include "bfi_cbreg.h" 21 #include "bfa_defs.h" 22 23 BFA_TRC_FILE(CNA, IOC_CB); 24 25 /* 26 * forward declarations 27 */ 28 static bfa_boolean_t bfa_ioc_cb_firmware_lock(struct bfa_ioc_s *ioc); 29 static void bfa_ioc_cb_firmware_unlock(struct bfa_ioc_s *ioc); 30 static void bfa_ioc_cb_reg_init(struct bfa_ioc_s *ioc); 31 static void bfa_ioc_cb_map_port(struct bfa_ioc_s *ioc); 32 static void bfa_ioc_cb_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix); 33 static void bfa_ioc_cb_notify_fail(struct bfa_ioc_s *ioc); 34 static void bfa_ioc_cb_ownership_reset(struct bfa_ioc_s *ioc); 35 static bfa_boolean_t bfa_ioc_cb_sync_start(struct bfa_ioc_s *ioc); 36 static void bfa_ioc_cb_sync_join(struct bfa_ioc_s *ioc); 37 static void bfa_ioc_cb_sync_leave(struct bfa_ioc_s *ioc); 38 static void bfa_ioc_cb_sync_ack(struct bfa_ioc_s *ioc); 39 static bfa_boolean_t bfa_ioc_cb_sync_complete(struct bfa_ioc_s *ioc); 40 41 static struct bfa_ioc_hwif_s hwif_cb; 42 43 /* 44 * Called from bfa_ioc_attach() to map asic specific calls. 45 */ 46 void 47 bfa_ioc_set_cb_hwif(struct bfa_ioc_s *ioc) 48 { 49 hwif_cb.ioc_pll_init = bfa_ioc_cb_pll_init; 50 hwif_cb.ioc_firmware_lock = bfa_ioc_cb_firmware_lock; 51 hwif_cb.ioc_firmware_unlock = bfa_ioc_cb_firmware_unlock; 52 hwif_cb.ioc_reg_init = bfa_ioc_cb_reg_init; 53 hwif_cb.ioc_map_port = bfa_ioc_cb_map_port; 54 hwif_cb.ioc_isr_mode_set = bfa_ioc_cb_isr_mode_set; 55 hwif_cb.ioc_notify_fail = bfa_ioc_cb_notify_fail; 56 hwif_cb.ioc_ownership_reset = bfa_ioc_cb_ownership_reset; 57 hwif_cb.ioc_sync_start = bfa_ioc_cb_sync_start; 58 hwif_cb.ioc_sync_join = bfa_ioc_cb_sync_join; 59 hwif_cb.ioc_sync_leave = bfa_ioc_cb_sync_leave; 60 hwif_cb.ioc_sync_ack = bfa_ioc_cb_sync_ack; 61 hwif_cb.ioc_sync_complete = bfa_ioc_cb_sync_complete; 62 63 ioc->ioc_hwif = &hwif_cb; 64 } 65 66 /* 67 * Return true if firmware of current driver matches the running firmware. 68 */ 69 static bfa_boolean_t 70 bfa_ioc_cb_firmware_lock(struct bfa_ioc_s *ioc) 71 { 72 struct bfi_ioc_image_hdr_s fwhdr; 73 uint32_t fwstate = readl(ioc->ioc_regs.ioc_fwstate); 74 75 if (fwstate == BFI_IOC_UNINIT) 76 return BFA_TRUE; 77 78 bfa_ioc_fwver_get(ioc, &fwhdr); 79 80 if (swab32(fwhdr.exec) == BFI_BOOT_TYPE_NORMAL) 81 return BFA_TRUE; 82 83 bfa_trc(ioc, fwstate); 84 bfa_trc(ioc, fwhdr.exec); 85 writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate); 86 87 return BFA_TRUE; 88 } 89 90 static void 91 bfa_ioc_cb_firmware_unlock(struct bfa_ioc_s *ioc) 92 { 93 } 94 95 /* 96 * Notify other functions on HB failure. 97 */ 98 static void 99 bfa_ioc_cb_notify_fail(struct bfa_ioc_s *ioc) 100 { 101 writel(__PSS_ERR_STATUS_SET, ioc->ioc_regs.err_set); 102 readl(ioc->ioc_regs.err_set); 103 } 104 105 /* 106 * Host to LPU mailbox message addresses 107 */ 108 static struct { u32 hfn_mbox, lpu_mbox, hfn_pgn; } iocreg_fnreg[] = { 109 { HOSTFN0_LPU_MBOX0_0, LPU_HOSTFN0_MBOX0_0, HOST_PAGE_NUM_FN0 }, 110 { HOSTFN1_LPU_MBOX0_8, LPU_HOSTFN1_MBOX0_8, HOST_PAGE_NUM_FN1 } 111 }; 112 113 /* 114 * Host <-> LPU mailbox command/status registers 115 */ 116 static struct { u32 hfn, lpu; } iocreg_mbcmd[] = { 117 118 { HOSTFN0_LPU0_CMD_STAT, LPU0_HOSTFN0_CMD_STAT }, 119 { HOSTFN1_LPU1_CMD_STAT, LPU1_HOSTFN1_CMD_STAT } 120 }; 121 122 static void 123 bfa_ioc_cb_reg_init(struct bfa_ioc_s *ioc) 124 { 125 void __iomem *rb; 126 int pcifn = bfa_ioc_pcifn(ioc); 127 128 rb = bfa_ioc_bar0(ioc); 129 130 ioc->ioc_regs.hfn_mbox = rb + iocreg_fnreg[pcifn].hfn_mbox; 131 ioc->ioc_regs.lpu_mbox = rb + iocreg_fnreg[pcifn].lpu_mbox; 132 ioc->ioc_regs.host_page_num_fn = rb + iocreg_fnreg[pcifn].hfn_pgn; 133 134 if (ioc->port_id == 0) { 135 ioc->ioc_regs.heartbeat = rb + BFA_IOC0_HBEAT_REG; 136 ioc->ioc_regs.ioc_fwstate = rb + BFA_IOC0_STATE_REG; 137 ioc->ioc_regs.alt_ioc_fwstate = rb + BFA_IOC1_STATE_REG; 138 } else { 139 ioc->ioc_regs.heartbeat = (rb + BFA_IOC1_HBEAT_REG); 140 ioc->ioc_regs.ioc_fwstate = (rb + BFA_IOC1_STATE_REG); 141 ioc->ioc_regs.alt_ioc_fwstate = (rb + BFA_IOC0_STATE_REG); 142 } 143 144 /* 145 * Host <-> LPU mailbox command/status registers 146 */ 147 ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd[pcifn].hfn; 148 ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd[pcifn].lpu; 149 150 /* 151 * PSS control registers 152 */ 153 ioc->ioc_regs.pss_ctl_reg = (rb + PSS_CTL_REG); 154 ioc->ioc_regs.pss_err_status_reg = (rb + PSS_ERR_STATUS_REG); 155 ioc->ioc_regs.app_pll_fast_ctl_reg = (rb + APP_PLL_400_CTL_REG); 156 ioc->ioc_regs.app_pll_slow_ctl_reg = (rb + APP_PLL_212_CTL_REG); 157 158 /* 159 * IOC semaphore registers and serialization 160 */ 161 ioc->ioc_regs.ioc_sem_reg = (rb + HOST_SEM0_REG); 162 ioc->ioc_regs.ioc_init_sem_reg = (rb + HOST_SEM2_REG); 163 164 /* 165 * sram memory access 166 */ 167 ioc->ioc_regs.smem_page_start = (rb + PSS_SMEM_PAGE_START); 168 ioc->ioc_regs.smem_pg0 = BFI_IOC_SMEM_PG0_CB; 169 170 /* 171 * err set reg : for notification of hb failure 172 */ 173 ioc->ioc_regs.err_set = (rb + ERR_SET_REG); 174 } 175 176 /* 177 * Initialize IOC to port mapping. 178 */ 179 180 static void 181 bfa_ioc_cb_map_port(struct bfa_ioc_s *ioc) 182 { 183 /* 184 * For crossbow, port id is same as pci function. 185 */ 186 ioc->port_id = bfa_ioc_pcifn(ioc); 187 188 bfa_trc(ioc, ioc->port_id); 189 } 190 191 /* 192 * Set interrupt mode for a function: INTX or MSIX 193 */ 194 static void 195 bfa_ioc_cb_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix) 196 { 197 } 198 199 /* 200 * Synchronized IOC failure processing routines 201 */ 202 static bfa_boolean_t 203 bfa_ioc_cb_sync_start(struct bfa_ioc_s *ioc) 204 { 205 return bfa_ioc_cb_sync_complete(ioc); 206 } 207 208 /* 209 * Cleanup hw semaphore and usecnt registers 210 */ 211 static void 212 bfa_ioc_cb_ownership_reset(struct bfa_ioc_s *ioc) 213 { 214 215 /* 216 * Read the hw sem reg to make sure that it is locked 217 * before we clear it. If it is not locked, writing 1 218 * will lock it instead of clearing it. 219 */ 220 readl(ioc->ioc_regs.ioc_sem_reg); 221 writel(1, ioc->ioc_regs.ioc_sem_reg); 222 } 223 224 /* 225 * Synchronized IOC failure processing routines 226 */ 227 static void 228 bfa_ioc_cb_sync_join(struct bfa_ioc_s *ioc) 229 { 230 } 231 232 static void 233 bfa_ioc_cb_sync_leave(struct bfa_ioc_s *ioc) 234 { 235 } 236 237 static void 238 bfa_ioc_cb_sync_ack(struct bfa_ioc_s *ioc) 239 { 240 writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate); 241 } 242 243 static bfa_boolean_t 244 bfa_ioc_cb_sync_complete(struct bfa_ioc_s *ioc) 245 { 246 uint32_t fwstate, alt_fwstate; 247 fwstate = readl(ioc->ioc_regs.ioc_fwstate); 248 249 /* 250 * At this point, this IOC is hoding the hw sem in the 251 * start path (fwcheck) OR in the disable/enable path 252 * OR to check if the other IOC has acknowledged failure. 253 * 254 * So, this IOC can be in UNINIT, INITING, DISABLED, FAIL 255 * or in MEMTEST states. In a normal scenario, this IOC 256 * can not be in OP state when this function is called. 257 * 258 * However, this IOC could still be in OP state when 259 * the OS driver is starting up, if the OptROM code has 260 * left it in that state. 261 * 262 * If we had marked this IOC's fwstate as BFI_IOC_FAIL 263 * in the failure case and now, if the fwstate is not 264 * BFI_IOC_FAIL it implies that the other PCI fn have 265 * reinitialized the ASIC or this IOC got disabled, so 266 * return TRUE. 267 */ 268 if (fwstate == BFI_IOC_UNINIT || 269 fwstate == BFI_IOC_INITING || 270 fwstate == BFI_IOC_DISABLED || 271 fwstate == BFI_IOC_MEMTEST || 272 fwstate == BFI_IOC_OP) 273 return BFA_TRUE; 274 else { 275 alt_fwstate = readl(ioc->ioc_regs.alt_ioc_fwstate); 276 if (alt_fwstate == BFI_IOC_FAIL || 277 alt_fwstate == BFI_IOC_DISABLED || 278 alt_fwstate == BFI_IOC_UNINIT || 279 alt_fwstate == BFI_IOC_INITING || 280 alt_fwstate == BFI_IOC_MEMTEST) 281 return BFA_TRUE; 282 else 283 return BFA_FALSE; 284 } 285 } 286 287 bfa_status_t 288 bfa_ioc_cb_pll_init(void __iomem *rb, bfa_boolean_t fcmode) 289 { 290 u32 pll_sclk, pll_fclk; 291 292 pll_sclk = __APP_PLL_212_ENABLE | __APP_PLL_212_LRESETN | 293 __APP_PLL_212_P0_1(3U) | 294 __APP_PLL_212_JITLMT0_1(3U) | 295 __APP_PLL_212_CNTLMT0_1(3U); 296 pll_fclk = __APP_PLL_400_ENABLE | __APP_PLL_400_LRESETN | 297 __APP_PLL_400_RSEL200500 | __APP_PLL_400_P0_1(3U) | 298 __APP_PLL_400_JITLMT0_1(3U) | 299 __APP_PLL_400_CNTLMT0_1(3U); 300 writel(BFI_IOC_UNINIT, (rb + BFA_IOC0_STATE_REG)); 301 writel(BFI_IOC_UNINIT, (rb + BFA_IOC1_STATE_REG)); 302 writel(0xffffffffU, (rb + HOSTFN0_INT_MSK)); 303 writel(0xffffffffU, (rb + HOSTFN1_INT_MSK)); 304 writel(0xffffffffU, (rb + HOSTFN0_INT_STATUS)); 305 writel(0xffffffffU, (rb + HOSTFN1_INT_STATUS)); 306 writel(0xffffffffU, (rb + HOSTFN0_INT_MSK)); 307 writel(0xffffffffU, (rb + HOSTFN1_INT_MSK)); 308 writel(__APP_PLL_212_LOGIC_SOFT_RESET, rb + APP_PLL_212_CTL_REG); 309 writel(__APP_PLL_212_BYPASS | __APP_PLL_212_LOGIC_SOFT_RESET, 310 rb + APP_PLL_212_CTL_REG); 311 writel(__APP_PLL_400_LOGIC_SOFT_RESET, rb + APP_PLL_400_CTL_REG); 312 writel(__APP_PLL_400_BYPASS | __APP_PLL_400_LOGIC_SOFT_RESET, 313 rb + APP_PLL_400_CTL_REG); 314 udelay(2); 315 writel(__APP_PLL_212_LOGIC_SOFT_RESET, rb + APP_PLL_212_CTL_REG); 316 writel(__APP_PLL_400_LOGIC_SOFT_RESET, rb + APP_PLL_400_CTL_REG); 317 writel(pll_sclk | __APP_PLL_212_LOGIC_SOFT_RESET, 318 rb + APP_PLL_212_CTL_REG); 319 writel(pll_fclk | __APP_PLL_400_LOGIC_SOFT_RESET, 320 rb + APP_PLL_400_CTL_REG); 321 udelay(2000); 322 writel(0xffffffffU, (rb + HOSTFN0_INT_STATUS)); 323 writel(0xffffffffU, (rb + HOSTFN1_INT_STATUS)); 324 writel(pll_sclk, (rb + APP_PLL_212_CTL_REG)); 325 writel(pll_fclk, (rb + APP_PLL_400_CTL_REG)); 326 327 return BFA_STATUS_OK; 328 } 329