2 * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
6 * Linux driver for Brocade Fibre Channel Host Bus Adapter.
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
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.
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>
28 BFA_TRC_FILE(CNA, IOC_CB);
31 * forward declarations
33 static bfa_status_t bfa_ioc_cb_pll_init(struct bfa_ioc_s *ioc);
34 static bfa_boolean_t bfa_ioc_cb_firmware_lock(struct bfa_ioc_s *ioc);
35 static void bfa_ioc_cb_firmware_unlock(struct bfa_ioc_s *ioc);
36 static u32 *bfa_ioc_cb_fwimg_get_chunk(struct bfa_ioc_s *ioc, u32 off);
37 static u32 bfa_ioc_cb_fwimg_get_size(struct bfa_ioc_s *ioc);
38 static void bfa_ioc_cb_reg_init(struct bfa_ioc_s *ioc);
39 static void bfa_ioc_cb_map_port(struct bfa_ioc_s *ioc);
40 static void bfa_ioc_cb_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix);
41 static void bfa_ioc_cb_notify_hbfail(struct bfa_ioc_s *ioc);
42 static void bfa_ioc_cb_ownership_reset(struct bfa_ioc_s *ioc);
44 struct bfa_ioc_hwif_s hwif_cb = {
46 bfa_ioc_cb_firmware_lock,
47 bfa_ioc_cb_firmware_unlock,
48 bfa_ioc_cb_fwimg_get_chunk,
49 bfa_ioc_cb_fwimg_get_size,
52 bfa_ioc_cb_isr_mode_set,
53 bfa_ioc_cb_notify_hbfail,
54 bfa_ioc_cb_ownership_reset,
58 * Called from bfa_ioc_attach() to map asic specific calls.
61 bfa_ioc_set_cb_hwif(struct bfa_ioc_s *ioc)
63 ioc->ioc_hwif = &hwif_cb;
67 bfa_ioc_cb_fwimg_get_chunk(struct bfa_ioc_s *ioc, u32 off)
69 return bfi_image_cb_get_chunk(off);
73 bfa_ioc_cb_fwimg_get_size(struct bfa_ioc_s *ioc)
75 return bfi_image_cb_size;
79 * Return true if firmware of current driver matches the running firmware.
82 bfa_ioc_cb_firmware_lock(struct bfa_ioc_s *ioc)
88 bfa_ioc_cb_firmware_unlock(struct bfa_ioc_s *ioc)
93 * Notify other functions on HB failure.
96 bfa_ioc_cb_notify_hbfail(struct bfa_ioc_s *ioc)
98 bfa_reg_write(ioc->ioc_regs.err_set, __PSS_ERR_STATUS_SET);
99 bfa_reg_read(ioc->ioc_regs.err_set);
103 * Host to LPU mailbox message addresses
105 static struct { u32 hfn_mbox, lpu_mbox, hfn_pgn; } iocreg_fnreg[] = {
106 { HOSTFN0_LPU_MBOX0_0, LPU_HOSTFN0_MBOX0_0, HOST_PAGE_NUM_FN0 },
107 { HOSTFN1_LPU_MBOX0_8, LPU_HOSTFN1_MBOX0_8, HOST_PAGE_NUM_FN1 }
111 * Host <-> LPU mailbox command/status registers
113 static struct { u32 hfn, lpu; } iocreg_mbcmd[] = {
114 { HOSTFN0_LPU0_CMD_STAT, LPU0_HOSTFN0_CMD_STAT },
115 { HOSTFN1_LPU1_CMD_STAT, LPU1_HOSTFN1_CMD_STAT }
119 bfa_ioc_cb_reg_init(struct bfa_ioc_s *ioc)
122 int pcifn = bfa_ioc_pcifn(ioc);
124 rb = bfa_ioc_bar0(ioc);
126 ioc->ioc_regs.hfn_mbox = rb + iocreg_fnreg[pcifn].hfn_mbox;
127 ioc->ioc_regs.lpu_mbox = rb + iocreg_fnreg[pcifn].lpu_mbox;
128 ioc->ioc_regs.host_page_num_fn = rb + iocreg_fnreg[pcifn].hfn_pgn;
130 if (ioc->port_id == 0) {
131 ioc->ioc_regs.heartbeat = rb + BFA_IOC0_HBEAT_REG;
132 ioc->ioc_regs.ioc_fwstate = rb + BFA_IOC0_STATE_REG;
134 ioc->ioc_regs.heartbeat = (rb + BFA_IOC1_HBEAT_REG);
135 ioc->ioc_regs.ioc_fwstate = (rb + BFA_IOC1_STATE_REG);
139 * Host <-> LPU mailbox command/status registers
141 ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd[pcifn].hfn;
142 ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd[pcifn].lpu;
145 * PSS control registers
147 ioc->ioc_regs.pss_ctl_reg = (rb + PSS_CTL_REG);
148 ioc->ioc_regs.pss_err_status_reg = (rb + PSS_ERR_STATUS_REG);
149 ioc->ioc_regs.app_pll_fast_ctl_reg = (rb + APP_PLL_400_CTL_REG);
150 ioc->ioc_regs.app_pll_slow_ctl_reg = (rb + APP_PLL_212_CTL_REG);
153 * IOC semaphore registers and serialization
155 ioc->ioc_regs.ioc_sem_reg = (rb + HOST_SEM0_REG);
156 ioc->ioc_regs.ioc_init_sem_reg = (rb + HOST_SEM2_REG);
161 ioc->ioc_regs.smem_page_start = (rb + PSS_SMEM_PAGE_START);
162 ioc->ioc_regs.smem_pg0 = BFI_IOC_SMEM_PG0_CB;
165 * err set reg : for notification of hb failure
167 ioc->ioc_regs.err_set = (rb + ERR_SET_REG);
171 * Initialize IOC to port mapping.
174 bfa_ioc_cb_map_port(struct bfa_ioc_s *ioc)
177 * For crossbow, port id is same as pci function.
179 ioc->port_id = bfa_ioc_pcifn(ioc);
180 bfa_trc(ioc, ioc->port_id);
184 * Set interrupt mode for a function: INTX or MSIX
187 bfa_ioc_cb_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix)
192 bfa_ioc_cb_pll_init(struct bfa_ioc_s *ioc)
194 bfa_os_addr_t rb = ioc->pcidev.pci_bar_kva;
195 u32 pll_sclk, pll_fclk;
198 * Hold semaphore so that nobody can access the chip during init.
200 bfa_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg);
202 pll_sclk = __APP_PLL_212_ENABLE | __APP_PLL_212_LRESETN |
203 __APP_PLL_212_P0_1(3U) |
204 __APP_PLL_212_JITLMT0_1(3U) |
205 __APP_PLL_212_CNTLMT0_1(3U);
206 pll_fclk = __APP_PLL_400_ENABLE | __APP_PLL_400_LRESETN |
207 __APP_PLL_400_RSEL200500 | __APP_PLL_400_P0_1(3U) |
208 __APP_PLL_400_JITLMT0_1(3U) |
209 __APP_PLL_400_CNTLMT0_1(3U);
211 bfa_reg_write((rb + BFA_IOC0_STATE_REG), BFI_IOC_UNINIT);
212 bfa_reg_write((rb + BFA_IOC1_STATE_REG), BFI_IOC_UNINIT);
214 bfa_reg_write((rb + HOSTFN0_INT_MSK), 0xffffffffU);
215 bfa_reg_write((rb + HOSTFN1_INT_MSK), 0xffffffffU);
216 bfa_reg_write((rb + HOSTFN0_INT_STATUS), 0xffffffffU);
217 bfa_reg_write((rb + HOSTFN1_INT_STATUS), 0xffffffffU);
218 bfa_reg_write((rb + HOSTFN0_INT_MSK), 0xffffffffU);
219 bfa_reg_write((rb + HOSTFN1_INT_MSK), 0xffffffffU);
221 bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg,
222 __APP_PLL_212_LOGIC_SOFT_RESET);
223 bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg,
224 __APP_PLL_212_BYPASS |
225 __APP_PLL_212_LOGIC_SOFT_RESET);
226 bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg,
227 __APP_PLL_400_LOGIC_SOFT_RESET);
228 bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg,
229 __APP_PLL_400_BYPASS |
230 __APP_PLL_400_LOGIC_SOFT_RESET);
232 bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg,
233 __APP_PLL_212_LOGIC_SOFT_RESET);
234 bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg,
235 __APP_PLL_400_LOGIC_SOFT_RESET);
237 bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg,
238 pll_sclk | __APP_PLL_212_LOGIC_SOFT_RESET);
239 bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg,
240 pll_fclk | __APP_PLL_400_LOGIC_SOFT_RESET);
243 * Wait for PLLs to lock.
246 bfa_reg_write((rb + HOSTFN0_INT_STATUS), 0xffffffffU);
247 bfa_reg_write((rb + HOSTFN1_INT_STATUS), 0xffffffffU);
249 bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg, pll_sclk);
250 bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg, pll_fclk);
255 bfa_ioc_sem_release(ioc->ioc_regs.ioc_init_sem_reg);
257 return BFA_STATUS_OK;
261 * Cleanup hw semaphore and usecnt registers
264 bfa_ioc_cb_ownership_reset(struct bfa_ioc_s *ioc)
268 * Read the hw sem reg to make sure that it is locked
269 * before we clear it. If it is not locked, writing 1
270 * will lock it instead of clearing it.
272 bfa_reg_read(ioc->ioc_regs.ioc_sem_reg);
273 bfa_ioc_hw_sem_release(ioc);