blob: 870046e32c8dee3bab808b92959161c41f914c98 [file] [log] [blame]
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001/*
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/*
26 * forward declarations
27 */
28static bool bfa_ioc_ct_firmware_lock(struct bfa_ioc *ioc);
29static void bfa_ioc_ct_firmware_unlock(struct bfa_ioc *ioc);
30static void bfa_ioc_ct_reg_init(struct bfa_ioc *ioc);
31static void bfa_ioc_ct_map_port(struct bfa_ioc *ioc);
32static void bfa_ioc_ct_isr_mode_set(struct bfa_ioc *ioc, bool msix);
33static void bfa_ioc_ct_notify_hbfail(struct bfa_ioc *ioc);
34static void bfa_ioc_ct_ownership_reset(struct bfa_ioc *ioc);
35
36struct bfa_ioc_hwif hwif_ct;
37
38/**
39 * Called from bfa_ioc_attach() to map asic specific calls.
40 */
41void
42bfa_ioc_set_ct_hwif(struct bfa_ioc *ioc)
43{
44 hwif_ct.ioc_pll_init = bfa_ioc_ct_pll_init;
45 hwif_ct.ioc_firmware_lock = bfa_ioc_ct_firmware_lock;
46 hwif_ct.ioc_firmware_unlock = bfa_ioc_ct_firmware_unlock;
47 hwif_ct.ioc_reg_init = bfa_ioc_ct_reg_init;
48 hwif_ct.ioc_map_port = bfa_ioc_ct_map_port;
49 hwif_ct.ioc_isr_mode_set = bfa_ioc_ct_isr_mode_set;
50 hwif_ct.ioc_notify_hbfail = bfa_ioc_ct_notify_hbfail;
51 hwif_ct.ioc_ownership_reset = bfa_ioc_ct_ownership_reset;
52
53 ioc->ioc_hwif = &hwif_ct;
54}
55
56/**
57 * Return true if firmware of current driver matches the running firmware.
58 */
59static bool
60bfa_ioc_ct_firmware_lock(struct bfa_ioc *ioc)
61{
62 enum bfi_ioc_state ioc_fwstate;
63 u32 usecnt;
64 struct bfi_ioc_image_hdr fwhdr;
65
66 /**
67 * Firmware match check is relevant only for CNA.
68 */
69 if (!ioc->cna)
70 return true;
71
72 /**
73 * If bios boot (flash based) -- do not increment usage count
74 */
75 if (bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)) <
76 BFA_IOC_FWIMG_MINSZ)
77 return true;
78
79 bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg);
80 usecnt = readl(ioc->ioc_regs.ioc_usage_reg);
81
82 /**
83 * If usage count is 0, always return TRUE.
84 */
85 if (usecnt == 0) {
86 writel(1, ioc->ioc_regs.ioc_usage_reg);
87 bfa_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg);
88 return true;
89 }
90
91 ioc_fwstate = readl(ioc->ioc_regs.ioc_fwstate);
92
93 /**
94 * Use count cannot be non-zero and chip in uninitialized state.
95 */
96 BUG_ON(!(ioc_fwstate != BFI_IOC_UNINIT));
97
98 /**
99 * Check if another driver with a different firmware is active
100 */
101 bfa_ioc_fwver_get(ioc, &fwhdr);
102 if (!bfa_ioc_fwver_cmp(ioc, &fwhdr)) {
103 bfa_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg);
104 return false;
105 }
106
107 /**
108 * Same firmware version. Increment the reference count.
109 */
110 usecnt++;
111 writel(usecnt, ioc->ioc_regs.ioc_usage_reg);
112 bfa_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg);
113 return true;
114}
115
116static void
117bfa_ioc_ct_firmware_unlock(struct bfa_ioc *ioc)
118{
119 u32 usecnt;
120
121 /**
122 * Firmware lock is relevant only for CNA.
123 */
124 if (!ioc->cna)
125 return;
126
127 /**
128 * If bios boot (flash based) -- do not decrement usage count
129 */
130 if (bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)) <
131 BFA_IOC_FWIMG_MINSZ)
132 return;
133
134 /**
135 * decrement usage count
136 */
137 bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg);
138 usecnt = readl(ioc->ioc_regs.ioc_usage_reg);
139 BUG_ON(!(usecnt > 0));
140
141 usecnt--;
142 writel(usecnt, ioc->ioc_regs.ioc_usage_reg);
143
144 bfa_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg);
145}
146
147/**
148 * Notify other functions on HB failure.
149 */
150static void
151bfa_ioc_ct_notify_hbfail(struct bfa_ioc *ioc)
152{
153 if (ioc->cna) {
154 writel(__FW_INIT_HALT_P, ioc->ioc_regs.ll_halt);
155 /* Wait for halt to take effect */
156 readl(ioc->ioc_regs.ll_halt);
157 } else {
158 writel(__PSS_ERR_STATUS_SET, ioc->ioc_regs.err_set);
159 readl(ioc->ioc_regs.err_set);
160 }
161}
162
163/**
164 * Host to LPU mailbox message addresses
165 */
166static struct { u32 hfn_mbox, lpu_mbox, hfn_pgn; } iocreg_fnreg[] = {
167 { HOSTFN0_LPU_MBOX0_0, LPU_HOSTFN0_MBOX0_0, HOST_PAGE_NUM_FN0 },
168 { HOSTFN1_LPU_MBOX0_8, LPU_HOSTFN1_MBOX0_8, HOST_PAGE_NUM_FN1 },
169 { HOSTFN2_LPU_MBOX0_0, LPU_HOSTFN2_MBOX0_0, HOST_PAGE_NUM_FN2 },
170 { HOSTFN3_LPU_MBOX0_8, LPU_HOSTFN3_MBOX0_8, HOST_PAGE_NUM_FN3 }
171};
172
173/**
174 * Host <-> LPU mailbox command/status registers - port 0
175 */
176static struct { u32 hfn, lpu; } iocreg_mbcmd_p0[] = {
177 { HOSTFN0_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN0_MBOX0_CMD_STAT },
178 { HOSTFN1_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN1_MBOX0_CMD_STAT },
179 { HOSTFN2_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN2_MBOX0_CMD_STAT },
180 { HOSTFN3_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN3_MBOX0_CMD_STAT }
181};
182
183/**
184 * Host <-> LPU mailbox command/status registers - port 1
185 */
186static struct { u32 hfn, lpu; } iocreg_mbcmd_p1[] = {
187 { HOSTFN0_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN0_MBOX0_CMD_STAT },
188 { HOSTFN1_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN1_MBOX0_CMD_STAT },
189 { HOSTFN2_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN2_MBOX0_CMD_STAT },
190 { HOSTFN3_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN3_MBOX0_CMD_STAT }
191};
192
193static void
194bfa_ioc_ct_reg_init(struct bfa_ioc *ioc)
195{
196 void __iomem *rb;
197 int pcifn = bfa_ioc_pcifn(ioc);
198
199 rb = bfa_ioc_bar0(ioc);
200
201 ioc->ioc_regs.hfn_mbox = rb + iocreg_fnreg[pcifn].hfn_mbox;
202 ioc->ioc_regs.lpu_mbox = rb + iocreg_fnreg[pcifn].lpu_mbox;
203 ioc->ioc_regs.host_page_num_fn = rb + iocreg_fnreg[pcifn].hfn_pgn;
204
205 if (ioc->port_id == 0) {
206 ioc->ioc_regs.heartbeat = rb + BFA_IOC0_HBEAT_REG;
207 ioc->ioc_regs.ioc_fwstate = rb + BFA_IOC0_STATE_REG;
208 ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd_p0[pcifn].hfn;
209 ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd_p0[pcifn].lpu;
210 ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P0;
211 } else {
212 ioc->ioc_regs.heartbeat = (rb + BFA_IOC1_HBEAT_REG);
213 ioc->ioc_regs.ioc_fwstate = (rb + BFA_IOC1_STATE_REG);
214 ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd_p1[pcifn].hfn;
215 ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd_p1[pcifn].lpu;
216 ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P1;
217 }
218
219 /*
220 * PSS control registers
221 */
222 ioc->ioc_regs.pss_ctl_reg = (rb + PSS_CTL_REG);
223 ioc->ioc_regs.pss_err_status_reg = (rb + PSS_ERR_STATUS_REG);
224 ioc->ioc_regs.app_pll_fast_ctl_reg = (rb + APP_PLL_425_CTL_REG);
225 ioc->ioc_regs.app_pll_slow_ctl_reg = (rb + APP_PLL_312_CTL_REG);
226
227 /*
228 * IOC semaphore registers and serialization
229 */
230 ioc->ioc_regs.ioc_sem_reg = (rb + HOST_SEM0_REG);
231 ioc->ioc_regs.ioc_usage_sem_reg = (rb + HOST_SEM1_REG);
232 ioc->ioc_regs.ioc_init_sem_reg = (rb + HOST_SEM2_REG);
233 ioc->ioc_regs.ioc_usage_reg = (rb + BFA_FW_USE_COUNT);
234
235 /**
236 * sram memory access
237 */
238 ioc->ioc_regs.smem_page_start = (rb + PSS_SMEM_PAGE_START);
239 ioc->ioc_regs.smem_pg0 = BFI_IOC_SMEM_PG0_CT;
240
241 /*
242 * err set reg : for notification of hb failure in fcmode
243 */
244 ioc->ioc_regs.err_set = (rb + ERR_SET_REG);
245}
246
247/**
248 * Initialize IOC to port mapping.
249 */
250
251#define FNC_PERS_FN_SHIFT(__fn) ((__fn) * 8)
252static void
253bfa_ioc_ct_map_port(struct bfa_ioc *ioc)
254{
255 void __iomem *rb = ioc->pcidev.pci_bar_kva;
256 u32 r32;
257
258 /**
259 * For catapult, base port id on personality register and IOC type
260 */
261 r32 = readl(rb + FNC_PERS_REG);
262 r32 >>= FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc));
263 ioc->port_id = (r32 & __F0_PORT_MAP_MK) >> __F0_PORT_MAP_SH;
264
265}
266
267/**
268 * Set interrupt mode for a function: INTX or MSIX
269 */
270static void
271bfa_ioc_ct_isr_mode_set(struct bfa_ioc *ioc, bool msix)
272{
273 void __iomem *rb = ioc->pcidev.pci_bar_kva;
274 u32 r32, mode;
275
276 r32 = readl(rb + FNC_PERS_REG);
277
278 mode = (r32 >> FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc))) &
279 __F0_INTX_STATUS;
280
281 /**
282 * If already in desired mode, do not change anything
283 */
284 if (!msix && mode)
285 return;
286
287 if (msix)
288 mode = __F0_INTX_STATUS_MSIX;
289 else
290 mode = __F0_INTX_STATUS_INTA;
291
292 r32 &= ~(__F0_INTX_STATUS << FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc)));
293 r32 |= (mode << FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc)));
294
295 writel(r32, rb + FNC_PERS_REG);
296}
297
298/**
299 * Cleanup hw semaphore and usecnt registers
300 */
301static void
302bfa_ioc_ct_ownership_reset(struct bfa_ioc *ioc)
303{
304 if (ioc->cna) {
305 bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg);
306 writel(0, ioc->ioc_regs.ioc_usage_reg);
307 bfa_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg);
308 }
309
310 /*
311 * Read the hw sem reg to make sure that it is locked
312 * before we clear it. If it is not locked, writing 1
313 * will lock it instead of clearing it.
314 */
315 readl(ioc->ioc_regs.ioc_sem_reg);
316 bfa_ioc_hw_sem_release(ioc);
317}
318
319enum bfa_status
320bfa_ioc_ct_pll_init(void __iomem *rb, bool fcmode)
321{
322 u32 pll_sclk, pll_fclk, r32;
323
324 pll_sclk = __APP_PLL_312_LRESETN | __APP_PLL_312_ENARST |
325 __APP_PLL_312_RSEL200500 | __APP_PLL_312_P0_1(3U) |
326 __APP_PLL_312_JITLMT0_1(3U) |
327 __APP_PLL_312_CNTLMT0_1(1U);
328 pll_fclk = __APP_PLL_425_LRESETN | __APP_PLL_425_ENARST |
329 __APP_PLL_425_RSEL200500 | __APP_PLL_425_P0_1(3U) |
330 __APP_PLL_425_JITLMT0_1(3U) |
331 __APP_PLL_425_CNTLMT0_1(1U);
332 if (fcmode) {
333 writel(0, (rb + OP_MODE));
334 writel(__APP_EMS_CMLCKSEL |
335 __APP_EMS_REFCKBUFEN2 |
336 __APP_EMS_CHANNEL_SEL,
337 (rb + ETH_MAC_SER_REG));
338 } else {
339 writel(__GLOBAL_FCOE_MODE, (rb + OP_MODE));
340 writel(__APP_EMS_REFCKBUFEN1,
341 (rb + ETH_MAC_SER_REG));
342 }
343 writel(BFI_IOC_UNINIT, (rb + BFA_IOC0_STATE_REG));
344 writel(BFI_IOC_UNINIT, (rb + BFA_IOC1_STATE_REG));
345 writel(0xffffffffU, (rb + HOSTFN0_INT_MSK));
346 writel(0xffffffffU, (rb + HOSTFN1_INT_MSK));
347 writel(0xffffffffU, (rb + HOSTFN0_INT_STATUS));
348 writel(0xffffffffU, (rb + HOSTFN1_INT_STATUS));
349 writel(0xffffffffU, (rb + HOSTFN0_INT_MSK));
350 writel(0xffffffffU, (rb + HOSTFN1_INT_MSK));
351 writel(pll_sclk |
352 __APP_PLL_312_LOGIC_SOFT_RESET,
353 rb + APP_PLL_312_CTL_REG);
354 writel(pll_fclk |
355 __APP_PLL_425_LOGIC_SOFT_RESET,
356 rb + APP_PLL_425_CTL_REG);
357 writel(pll_sclk |
358 __APP_PLL_312_LOGIC_SOFT_RESET | __APP_PLL_312_ENABLE,
359 rb + APP_PLL_312_CTL_REG);
360 writel(pll_fclk |
361 __APP_PLL_425_LOGIC_SOFT_RESET | __APP_PLL_425_ENABLE,
362 rb + APP_PLL_425_CTL_REG);
363 readl(rb + HOSTFN0_INT_MSK);
364 udelay(2000);
365 writel(0xffffffffU, (rb + HOSTFN0_INT_STATUS));
366 writel(0xffffffffU, (rb + HOSTFN1_INT_STATUS));
367 writel(pll_sclk |
368 __APP_PLL_312_ENABLE,
369 rb + APP_PLL_312_CTL_REG);
370 writel(pll_fclk |
371 __APP_PLL_425_ENABLE,
372 rb + APP_PLL_425_CTL_REG);
373 if (!fcmode) {
374 writel(__PMM_1T_RESET_P, (rb + PMM_1T_RESET_REG_P0));
375 writel(__PMM_1T_RESET_P, (rb + PMM_1T_RESET_REG_P1));
376 }
377 r32 = readl((rb + PSS_CTL_REG));
378 r32 &= ~__PSS_LMEM_RESET;
379 writel(r32, (rb + PSS_CTL_REG));
380 udelay(1000);
381 if (!fcmode) {
382 writel(0, (rb + PMM_1T_RESET_REG_P0));
383 writel(0, (rb + PMM_1T_RESET_REG_P1));
384 }
385
386 writel(__EDRAM_BISTR_START, (rb + MBIST_CTL_REG));
387 udelay(1000);
388 r32 = readl((rb + MBIST_STAT_REG));
389 writel(0, (rb + MBIST_CTL_REG));
390 return BFA_STATUS_OK;
391}