diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/net/bna/bfa_ioc_ct.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'drivers/net/bna/bfa_ioc_ct.c')
-rw-r--r-- | drivers/net/bna/bfa_ioc_ct.c | 516 |
1 files changed, 516 insertions, 0 deletions
diff --git a/drivers/net/bna/bfa_ioc_ct.c b/drivers/net/bna/bfa_ioc_ct.c new file mode 100644 index 000000000000..87aecdf22cf9 --- /dev/null +++ b/drivers/net/bna/bfa_ioc_ct.c | |||
@@ -0,0 +1,516 @@ | |||
1 | /* | ||
2 | * Linux network driver for Brocade Converged Network Adapter. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms of the GNU General Public License (GPL) Version 2 as | ||
6 | * published by the Free Software Foundation | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, but | ||
9 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
11 | * General Public License for more details. | ||
12 | */ | ||
13 | /* | ||
14 | * Copyright (c) 2005-2010 Brocade Communications Systems, Inc. | ||
15 | * All rights reserved | ||
16 | * www.brocade.com | ||
17 | */ | ||
18 | |||
19 | #include "bfa_ioc.h" | ||
20 | #include "cna.h" | ||
21 | #include "bfi.h" | ||
22 | #include "bfi_ctreg.h" | ||
23 | #include "bfa_defs.h" | ||
24 | |||
25 | #define bfa_ioc_ct_sync_pos(__ioc) \ | ||
26 | ((u32) (1 << bfa_ioc_pcifn(__ioc))) | ||
27 | #define BFA_IOC_SYNC_REQD_SH 16 | ||
28 | #define bfa_ioc_ct_get_sync_ackd(__val) (__val & 0x0000ffff) | ||
29 | #define bfa_ioc_ct_clear_sync_ackd(__val) (__val & 0xffff0000) | ||
30 | #define bfa_ioc_ct_get_sync_reqd(__val) (__val >> BFA_IOC_SYNC_REQD_SH) | ||
31 | #define bfa_ioc_ct_sync_reqd_pos(__ioc) \ | ||
32 | (bfa_ioc_ct_sync_pos(__ioc) << BFA_IOC_SYNC_REQD_SH) | ||
33 | |||
34 | /* | ||
35 | * forward declarations | ||
36 | */ | ||
37 | static bool bfa_ioc_ct_firmware_lock(struct bfa_ioc *ioc); | ||
38 | static void bfa_ioc_ct_firmware_unlock(struct bfa_ioc *ioc); | ||
39 | static void bfa_ioc_ct_reg_init(struct bfa_ioc *ioc); | ||
40 | static void bfa_ioc_ct_map_port(struct bfa_ioc *ioc); | ||
41 | static void bfa_ioc_ct_isr_mode_set(struct bfa_ioc *ioc, bool msix); | ||
42 | static void bfa_ioc_ct_notify_fail(struct bfa_ioc *ioc); | ||
43 | static void bfa_ioc_ct_ownership_reset(struct bfa_ioc *ioc); | ||
44 | static bool bfa_ioc_ct_sync_start(struct bfa_ioc *ioc); | ||
45 | static void bfa_ioc_ct_sync_join(struct bfa_ioc *ioc); | ||
46 | static void bfa_ioc_ct_sync_leave(struct bfa_ioc *ioc); | ||
47 | static void bfa_ioc_ct_sync_ack(struct bfa_ioc *ioc); | ||
48 | static bool bfa_ioc_ct_sync_complete(struct bfa_ioc *ioc); | ||
49 | static enum bfa_status bfa_ioc_ct_pll_init(void __iomem *rb, bool fcmode); | ||
50 | |||
51 | static struct bfa_ioc_hwif nw_hwif_ct; | ||
52 | |||
53 | /** | ||
54 | * Called from bfa_ioc_attach() to map asic specific calls. | ||
55 | */ | ||
56 | void | ||
57 | bfa_nw_ioc_set_ct_hwif(struct bfa_ioc *ioc) | ||
58 | { | ||
59 | nw_hwif_ct.ioc_pll_init = bfa_ioc_ct_pll_init; | ||
60 | nw_hwif_ct.ioc_firmware_lock = bfa_ioc_ct_firmware_lock; | ||
61 | nw_hwif_ct.ioc_firmware_unlock = bfa_ioc_ct_firmware_unlock; | ||
62 | nw_hwif_ct.ioc_reg_init = bfa_ioc_ct_reg_init; | ||
63 | nw_hwif_ct.ioc_map_port = bfa_ioc_ct_map_port; | ||
64 | nw_hwif_ct.ioc_isr_mode_set = bfa_ioc_ct_isr_mode_set; | ||
65 | nw_hwif_ct.ioc_notify_fail = bfa_ioc_ct_notify_fail; | ||
66 | nw_hwif_ct.ioc_ownership_reset = bfa_ioc_ct_ownership_reset; | ||
67 | nw_hwif_ct.ioc_sync_start = bfa_ioc_ct_sync_start; | ||
68 | nw_hwif_ct.ioc_sync_join = bfa_ioc_ct_sync_join; | ||
69 | nw_hwif_ct.ioc_sync_leave = bfa_ioc_ct_sync_leave; | ||
70 | nw_hwif_ct.ioc_sync_ack = bfa_ioc_ct_sync_ack; | ||
71 | nw_hwif_ct.ioc_sync_complete = bfa_ioc_ct_sync_complete; | ||
72 | |||
73 | ioc->ioc_hwif = &nw_hwif_ct; | ||
74 | } | ||
75 | |||
76 | /** | ||
77 | * Return true if firmware of current driver matches the running firmware. | ||
78 | */ | ||
79 | static bool | ||
80 | bfa_ioc_ct_firmware_lock(struct bfa_ioc *ioc) | ||
81 | { | ||
82 | enum bfi_ioc_state ioc_fwstate; | ||
83 | u32 usecnt; | ||
84 | struct bfi_ioc_image_hdr fwhdr; | ||
85 | |||
86 | /** | ||
87 | * Firmware match check is relevant only for CNA. | ||
88 | */ | ||
89 | if (!ioc->cna) | ||
90 | return true; | ||
91 | |||
92 | /** | ||
93 | * If bios boot (flash based) -- do not increment usage count | ||
94 | */ | ||
95 | if (bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)) < | ||
96 | BFA_IOC_FWIMG_MINSZ) | ||
97 | return true; | ||
98 | |||
99 | bfa_nw_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg); | ||
100 | usecnt = readl(ioc->ioc_regs.ioc_usage_reg); | ||
101 | |||
102 | /** | ||
103 | * If usage count is 0, always return TRUE. | ||
104 | */ | ||
105 | if (usecnt == 0) { | ||
106 | writel(1, ioc->ioc_regs.ioc_usage_reg); | ||
107 | bfa_nw_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg); | ||
108 | writel(0, ioc->ioc_regs.ioc_fail_sync); | ||
109 | return true; | ||
110 | } | ||
111 | |||
112 | ioc_fwstate = readl(ioc->ioc_regs.ioc_fwstate); | ||
113 | |||
114 | /** | ||
115 | * Use count cannot be non-zero and chip in uninitialized state. | ||
116 | */ | ||
117 | BUG_ON(!(ioc_fwstate != BFI_IOC_UNINIT)); | ||
118 | |||
119 | /** | ||
120 | * Check if another driver with a different firmware is active | ||
121 | */ | ||
122 | bfa_nw_ioc_fwver_get(ioc, &fwhdr); | ||
123 | if (!bfa_nw_ioc_fwver_cmp(ioc, &fwhdr)) { | ||
124 | bfa_nw_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg); | ||
125 | return false; | ||
126 | } | ||
127 | |||
128 | /** | ||
129 | * Same firmware version. Increment the reference count. | ||
130 | */ | ||
131 | usecnt++; | ||
132 | writel(usecnt, ioc->ioc_regs.ioc_usage_reg); | ||
133 | bfa_nw_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg); | ||
134 | return true; | ||
135 | } | ||
136 | |||
137 | static void | ||
138 | bfa_ioc_ct_firmware_unlock(struct bfa_ioc *ioc) | ||
139 | { | ||
140 | u32 usecnt; | ||
141 | |||
142 | /** | ||
143 | * Firmware lock is relevant only for CNA. | ||
144 | */ | ||
145 | if (!ioc->cna) | ||
146 | return; | ||
147 | |||
148 | /** | ||
149 | * If bios boot (flash based) -- do not decrement usage count | ||
150 | */ | ||
151 | if (bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)) < | ||
152 | BFA_IOC_FWIMG_MINSZ) | ||
153 | return; | ||
154 | |||
155 | /** | ||
156 | * decrement usage count | ||
157 | */ | ||
158 | bfa_nw_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg); | ||
159 | usecnt = readl(ioc->ioc_regs.ioc_usage_reg); | ||
160 | BUG_ON(!(usecnt > 0)); | ||
161 | |||
162 | usecnt--; | ||
163 | writel(usecnt, ioc->ioc_regs.ioc_usage_reg); | ||
164 | |||
165 | bfa_nw_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg); | ||
166 | } | ||
167 | |||
168 | /** | ||
169 | * Notify other functions on HB failure. | ||
170 | */ | ||
171 | static void | ||
172 | bfa_ioc_ct_notify_fail(struct bfa_ioc *ioc) | ||
173 | { | ||
174 | if (ioc->cna) { | ||
175 | writel(__FW_INIT_HALT_P, ioc->ioc_regs.ll_halt); | ||
176 | writel(__FW_INIT_HALT_P, ioc->ioc_regs.alt_ll_halt); | ||
177 | /* Wait for halt to take effect */ | ||
178 | readl(ioc->ioc_regs.ll_halt); | ||
179 | readl(ioc->ioc_regs.alt_ll_halt); | ||
180 | } else { | ||
181 | writel(__PSS_ERR_STATUS_SET, ioc->ioc_regs.err_set); | ||
182 | readl(ioc->ioc_regs.err_set); | ||
183 | } | ||
184 | } | ||
185 | |||
186 | /** | ||
187 | * Host to LPU mailbox message addresses | ||
188 | */ | ||
189 | static struct { u32 hfn_mbox, lpu_mbox, hfn_pgn; } iocreg_fnreg[] = { | ||
190 | { HOSTFN0_LPU_MBOX0_0, LPU_HOSTFN0_MBOX0_0, HOST_PAGE_NUM_FN0 }, | ||
191 | { HOSTFN1_LPU_MBOX0_8, LPU_HOSTFN1_MBOX0_8, HOST_PAGE_NUM_FN1 }, | ||
192 | { HOSTFN2_LPU_MBOX0_0, LPU_HOSTFN2_MBOX0_0, HOST_PAGE_NUM_FN2 }, | ||
193 | { HOSTFN3_LPU_MBOX0_8, LPU_HOSTFN3_MBOX0_8, HOST_PAGE_NUM_FN3 } | ||
194 | }; | ||
195 | |||
196 | /** | ||
197 | * Host <-> LPU mailbox command/status registers - port 0 | ||
198 | */ | ||
199 | static struct { u32 hfn, lpu; } iocreg_mbcmd_p0[] = { | ||
200 | { HOSTFN0_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN0_MBOX0_CMD_STAT }, | ||
201 | { HOSTFN1_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN1_MBOX0_CMD_STAT }, | ||
202 | { HOSTFN2_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN2_MBOX0_CMD_STAT }, | ||
203 | { HOSTFN3_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN3_MBOX0_CMD_STAT } | ||
204 | }; | ||
205 | |||
206 | /** | ||
207 | * Host <-> LPU mailbox command/status registers - port 1 | ||
208 | */ | ||
209 | static struct { u32 hfn, lpu; } iocreg_mbcmd_p1[] = { | ||
210 | { HOSTFN0_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN0_MBOX0_CMD_STAT }, | ||
211 | { HOSTFN1_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN1_MBOX0_CMD_STAT }, | ||
212 | { HOSTFN2_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN2_MBOX0_CMD_STAT }, | ||
213 | { HOSTFN3_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN3_MBOX0_CMD_STAT } | ||
214 | }; | ||
215 | |||
216 | static void | ||
217 | bfa_ioc_ct_reg_init(struct bfa_ioc *ioc) | ||
218 | { | ||
219 | void __iomem *rb; | ||
220 | int pcifn = bfa_ioc_pcifn(ioc); | ||
221 | |||
222 | rb = bfa_ioc_bar0(ioc); | ||
223 | |||
224 | ioc->ioc_regs.hfn_mbox = rb + iocreg_fnreg[pcifn].hfn_mbox; | ||
225 | ioc->ioc_regs.lpu_mbox = rb + iocreg_fnreg[pcifn].lpu_mbox; | ||
226 | ioc->ioc_regs.host_page_num_fn = rb + iocreg_fnreg[pcifn].hfn_pgn; | ||
227 | |||
228 | if (ioc->port_id == 0) { | ||
229 | ioc->ioc_regs.heartbeat = rb + BFA_IOC0_HBEAT_REG; | ||
230 | ioc->ioc_regs.ioc_fwstate = rb + BFA_IOC0_STATE_REG; | ||
231 | ioc->ioc_regs.alt_ioc_fwstate = rb + BFA_IOC1_STATE_REG; | ||
232 | ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd_p0[pcifn].hfn; | ||
233 | ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd_p0[pcifn].lpu; | ||
234 | ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P0; | ||
235 | ioc->ioc_regs.alt_ll_halt = rb + FW_INIT_HALT_P1; | ||
236 | } else { | ||
237 | ioc->ioc_regs.heartbeat = (rb + BFA_IOC1_HBEAT_REG); | ||
238 | ioc->ioc_regs.ioc_fwstate = (rb + BFA_IOC1_STATE_REG); | ||
239 | ioc->ioc_regs.alt_ioc_fwstate = rb + BFA_IOC0_STATE_REG; | ||
240 | ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd_p1[pcifn].hfn; | ||
241 | ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd_p1[pcifn].lpu; | ||
242 | ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P1; | ||
243 | ioc->ioc_regs.alt_ll_halt = rb + FW_INIT_HALT_P0; | ||
244 | } | ||
245 | |||
246 | /* | ||
247 | * PSS control registers | ||
248 | */ | ||
249 | ioc->ioc_regs.pss_ctl_reg = (rb + PSS_CTL_REG); | ||
250 | ioc->ioc_regs.pss_err_status_reg = (rb + PSS_ERR_STATUS_REG); | ||
251 | ioc->ioc_regs.app_pll_fast_ctl_reg = (rb + APP_PLL_425_CTL_REG); | ||
252 | ioc->ioc_regs.app_pll_slow_ctl_reg = (rb + APP_PLL_312_CTL_REG); | ||
253 | |||
254 | /* | ||
255 | * IOC semaphore registers and serialization | ||
256 | */ | ||
257 | ioc->ioc_regs.ioc_sem_reg = (rb + HOST_SEM0_REG); | ||
258 | ioc->ioc_regs.ioc_usage_sem_reg = (rb + HOST_SEM1_REG); | ||
259 | ioc->ioc_regs.ioc_init_sem_reg = (rb + HOST_SEM2_REG); | ||
260 | ioc->ioc_regs.ioc_usage_reg = (rb + BFA_FW_USE_COUNT); | ||
261 | ioc->ioc_regs.ioc_fail_sync = (rb + BFA_IOC_FAIL_SYNC); | ||
262 | |||
263 | /** | ||
264 | * sram memory access | ||
265 | */ | ||
266 | ioc->ioc_regs.smem_page_start = (rb + PSS_SMEM_PAGE_START); | ||
267 | ioc->ioc_regs.smem_pg0 = BFI_IOC_SMEM_PG0_CT; | ||
268 | |||
269 | /* | ||
270 | * err set reg : for notification of hb failure in fcmode | ||
271 | */ | ||
272 | ioc->ioc_regs.err_set = (rb + ERR_SET_REG); | ||
273 | } | ||
274 | |||
275 | /** | ||
276 | * Initialize IOC to port mapping. | ||
277 | */ | ||
278 | |||
279 | #define FNC_PERS_FN_SHIFT(__fn) ((__fn) * 8) | ||
280 | static void | ||
281 | bfa_ioc_ct_map_port(struct bfa_ioc *ioc) | ||
282 | { | ||
283 | void __iomem *rb = ioc->pcidev.pci_bar_kva; | ||
284 | u32 r32; | ||
285 | |||
286 | /** | ||
287 | * For catapult, base port id on personality register and IOC type | ||
288 | */ | ||
289 | r32 = readl(rb + FNC_PERS_REG); | ||
290 | r32 >>= FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc)); | ||
291 | ioc->port_id = (r32 & __F0_PORT_MAP_MK) >> __F0_PORT_MAP_SH; | ||
292 | |||
293 | } | ||
294 | |||
295 | /** | ||
296 | * Set interrupt mode for a function: INTX or MSIX | ||
297 | */ | ||
298 | static void | ||
299 | bfa_ioc_ct_isr_mode_set(struct bfa_ioc *ioc, bool msix) | ||
300 | { | ||
301 | void __iomem *rb = ioc->pcidev.pci_bar_kva; | ||
302 | u32 r32, mode; | ||
303 | |||
304 | r32 = readl(rb + FNC_PERS_REG); | ||
305 | |||
306 | mode = (r32 >> FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc))) & | ||
307 | __F0_INTX_STATUS; | ||
308 | |||
309 | /** | ||
310 | * If already in desired mode, do not change anything | ||
311 | */ | ||
312 | if (!msix && mode) | ||
313 | return; | ||
314 | |||
315 | if (msix) | ||
316 | mode = __F0_INTX_STATUS_MSIX; | ||
317 | else | ||
318 | mode = __F0_INTX_STATUS_INTA; | ||
319 | |||
320 | r32 &= ~(__F0_INTX_STATUS << FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc))); | ||
321 | r32 |= (mode << FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc))); | ||
322 | |||
323 | writel(r32, rb + FNC_PERS_REG); | ||
324 | } | ||
325 | |||
326 | /** | ||
327 | * Cleanup hw semaphore and usecnt registers | ||
328 | */ | ||
329 | static void | ||
330 | bfa_ioc_ct_ownership_reset(struct bfa_ioc *ioc) | ||
331 | { | ||
332 | if (ioc->cna) { | ||
333 | bfa_nw_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg); | ||
334 | writel(0, ioc->ioc_regs.ioc_usage_reg); | ||
335 | bfa_nw_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg); | ||
336 | } | ||
337 | |||
338 | /* | ||
339 | * Read the hw sem reg to make sure that it is locked | ||
340 | * before we clear it. If it is not locked, writing 1 | ||
341 | * will lock it instead of clearing it. | ||
342 | */ | ||
343 | readl(ioc->ioc_regs.ioc_sem_reg); | ||
344 | bfa_nw_ioc_hw_sem_release(ioc); | ||
345 | } | ||
346 | |||
347 | /** | ||
348 | * Synchronized IOC failure processing routines | ||
349 | */ | ||
350 | static bool | ||
351 | bfa_ioc_ct_sync_start(struct bfa_ioc *ioc) | ||
352 | { | ||
353 | u32 r32 = readl(ioc->ioc_regs.ioc_fail_sync); | ||
354 | u32 sync_reqd = bfa_ioc_ct_get_sync_reqd(r32); | ||
355 | |||
356 | /* | ||
357 | * Driver load time. If the sync required bit for this PCI fn | ||
358 | * is set, it is due to an unclean exit by the driver for this | ||
359 | * PCI fn in the previous incarnation. Whoever comes here first | ||
360 | * should clean it up, no matter which PCI fn. | ||
361 | */ | ||
362 | |||
363 | if (sync_reqd & bfa_ioc_ct_sync_pos(ioc)) { | ||
364 | writel(0, ioc->ioc_regs.ioc_fail_sync); | ||
365 | writel(1, ioc->ioc_regs.ioc_usage_reg); | ||
366 | writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate); | ||
367 | writel(BFI_IOC_UNINIT, ioc->ioc_regs.alt_ioc_fwstate); | ||
368 | return true; | ||
369 | } | ||
370 | |||
371 | return bfa_ioc_ct_sync_complete(ioc); | ||
372 | } | ||
373 | /** | ||
374 | * Synchronized IOC failure processing routines | ||
375 | */ | ||
376 | static void | ||
377 | bfa_ioc_ct_sync_join(struct bfa_ioc *ioc) | ||
378 | { | ||
379 | u32 r32 = readl(ioc->ioc_regs.ioc_fail_sync); | ||
380 | u32 sync_pos = bfa_ioc_ct_sync_reqd_pos(ioc); | ||
381 | |||
382 | writel((r32 | sync_pos), ioc->ioc_regs.ioc_fail_sync); | ||
383 | } | ||
384 | |||
385 | static void | ||
386 | bfa_ioc_ct_sync_leave(struct bfa_ioc *ioc) | ||
387 | { | ||
388 | u32 r32 = readl(ioc->ioc_regs.ioc_fail_sync); | ||
389 | u32 sync_msk = bfa_ioc_ct_sync_reqd_pos(ioc) | | ||
390 | bfa_ioc_ct_sync_pos(ioc); | ||
391 | |||
392 | writel((r32 & ~sync_msk), ioc->ioc_regs.ioc_fail_sync); | ||
393 | } | ||
394 | |||
395 | static void | ||
396 | bfa_ioc_ct_sync_ack(struct bfa_ioc *ioc) | ||
397 | { | ||
398 | u32 r32 = readl(ioc->ioc_regs.ioc_fail_sync); | ||
399 | |||
400 | writel((r32 | bfa_ioc_ct_sync_pos(ioc)), ioc->ioc_regs.ioc_fail_sync); | ||
401 | } | ||
402 | |||
403 | static bool | ||
404 | bfa_ioc_ct_sync_complete(struct bfa_ioc *ioc) | ||
405 | { | ||
406 | u32 r32 = readl(ioc->ioc_regs.ioc_fail_sync); | ||
407 | u32 sync_reqd = bfa_ioc_ct_get_sync_reqd(r32); | ||
408 | u32 sync_ackd = bfa_ioc_ct_get_sync_ackd(r32); | ||
409 | u32 tmp_ackd; | ||
410 | |||
411 | if (sync_ackd == 0) | ||
412 | return true; | ||
413 | |||
414 | /** | ||
415 | * The check below is to see whether any other PCI fn | ||
416 | * has reinitialized the ASIC (reset sync_ackd bits) | ||
417 | * and failed again while this IOC was waiting for hw | ||
418 | * semaphore (in bfa_iocpf_sm_semwait()). | ||
419 | */ | ||
420 | tmp_ackd = sync_ackd; | ||
421 | if ((sync_reqd & bfa_ioc_ct_sync_pos(ioc)) && | ||
422 | !(sync_ackd & bfa_ioc_ct_sync_pos(ioc))) | ||
423 | sync_ackd |= bfa_ioc_ct_sync_pos(ioc); | ||
424 | |||
425 | if (sync_reqd == sync_ackd) { | ||
426 | writel(bfa_ioc_ct_clear_sync_ackd(r32), | ||
427 | ioc->ioc_regs.ioc_fail_sync); | ||
428 | writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate); | ||
429 | writel(BFI_IOC_FAIL, ioc->ioc_regs.alt_ioc_fwstate); | ||
430 | return true; | ||
431 | } | ||
432 | |||
433 | /** | ||
434 | * If another PCI fn reinitialized and failed again while | ||
435 | * this IOC was waiting for hw sem, the sync_ackd bit for | ||
436 | * this IOC need to be set again to allow reinitialization. | ||
437 | */ | ||
438 | if (tmp_ackd != sync_ackd) | ||
439 | writel((r32 | sync_ackd), ioc->ioc_regs.ioc_fail_sync); | ||
440 | |||
441 | return false; | ||
442 | } | ||
443 | |||
444 | static enum bfa_status | ||
445 | bfa_ioc_ct_pll_init(void __iomem *rb, bool fcmode) | ||
446 | { | ||
447 | u32 pll_sclk, pll_fclk, r32; | ||
448 | |||
449 | pll_sclk = __APP_PLL_312_LRESETN | __APP_PLL_312_ENARST | | ||
450 | __APP_PLL_312_RSEL200500 | __APP_PLL_312_P0_1(3U) | | ||
451 | __APP_PLL_312_JITLMT0_1(3U) | | ||
452 | __APP_PLL_312_CNTLMT0_1(1U); | ||
453 | pll_fclk = __APP_PLL_425_LRESETN | __APP_PLL_425_ENARST | | ||
454 | __APP_PLL_425_RSEL200500 | __APP_PLL_425_P0_1(3U) | | ||
455 | __APP_PLL_425_JITLMT0_1(3U) | | ||
456 | __APP_PLL_425_CNTLMT0_1(1U); | ||
457 | if (fcmode) { | ||
458 | writel(0, (rb + OP_MODE)); | ||
459 | writel(__APP_EMS_CMLCKSEL | | ||
460 | __APP_EMS_REFCKBUFEN2 | | ||
461 | __APP_EMS_CHANNEL_SEL, | ||
462 | (rb + ETH_MAC_SER_REG)); | ||
463 | } else { | ||
464 | writel(__GLOBAL_FCOE_MODE, (rb + OP_MODE)); | ||
465 | writel(__APP_EMS_REFCKBUFEN1, | ||
466 | (rb + ETH_MAC_SER_REG)); | ||
467 | } | ||
468 | writel(BFI_IOC_UNINIT, (rb + BFA_IOC0_STATE_REG)); | ||
469 | writel(BFI_IOC_UNINIT, (rb + BFA_IOC1_STATE_REG)); | ||
470 | writel(0xffffffffU, (rb + HOSTFN0_INT_MSK)); | ||
471 | writel(0xffffffffU, (rb + HOSTFN1_INT_MSK)); | ||
472 | writel(0xffffffffU, (rb + HOSTFN0_INT_STATUS)); | ||
473 | writel(0xffffffffU, (rb + HOSTFN1_INT_STATUS)); | ||
474 | writel(0xffffffffU, (rb + HOSTFN0_INT_MSK)); | ||
475 | writel(0xffffffffU, (rb + HOSTFN1_INT_MSK)); | ||
476 | writel(pll_sclk | | ||
477 | __APP_PLL_312_LOGIC_SOFT_RESET, | ||
478 | rb + APP_PLL_312_CTL_REG); | ||
479 | writel(pll_fclk | | ||
480 | __APP_PLL_425_LOGIC_SOFT_RESET, | ||
481 | rb + APP_PLL_425_CTL_REG); | ||
482 | writel(pll_sclk | | ||
483 | __APP_PLL_312_LOGIC_SOFT_RESET | __APP_PLL_312_ENABLE, | ||
484 | rb + APP_PLL_312_CTL_REG); | ||
485 | writel(pll_fclk | | ||
486 | __APP_PLL_425_LOGIC_SOFT_RESET | __APP_PLL_425_ENABLE, | ||
487 | rb + APP_PLL_425_CTL_REG); | ||
488 | readl(rb + HOSTFN0_INT_MSK); | ||
489 | udelay(2000); | ||
490 | writel(0xffffffffU, (rb + HOSTFN0_INT_STATUS)); | ||
491 | writel(0xffffffffU, (rb + HOSTFN1_INT_STATUS)); | ||
492 | writel(pll_sclk | | ||
493 | __APP_PLL_312_ENABLE, | ||
494 | rb + APP_PLL_312_CTL_REG); | ||
495 | writel(pll_fclk | | ||
496 | __APP_PLL_425_ENABLE, | ||
497 | rb + APP_PLL_425_CTL_REG); | ||
498 | if (!fcmode) { | ||
499 | writel(__PMM_1T_RESET_P, (rb + PMM_1T_RESET_REG_P0)); | ||
500 | writel(__PMM_1T_RESET_P, (rb + PMM_1T_RESET_REG_P1)); | ||
501 | } | ||
502 | r32 = readl((rb + PSS_CTL_REG)); | ||
503 | r32 &= ~__PSS_LMEM_RESET; | ||
504 | writel(r32, (rb + PSS_CTL_REG)); | ||
505 | udelay(1000); | ||
506 | if (!fcmode) { | ||
507 | writel(0, (rb + PMM_1T_RESET_REG_P0)); | ||
508 | writel(0, (rb + PMM_1T_RESET_REG_P1)); | ||
509 | } | ||
510 | |||
511 | writel(__EDRAM_BISTR_START, (rb + MBIST_CTL_REG)); | ||
512 | udelay(1000); | ||
513 | r32 = readl((rb + MBIST_STAT_REG)); | ||
514 | writel(0, (rb + MBIST_CTL_REG)); | ||
515 | return BFA_STATUS_OK; | ||
516 | } | ||