Commit | Line | Data |
---|---|---|
0a20de44 | 1 | /* |
a36c61f9 | 2 | * Copyright (c) 2005-2010 Brocade Communications Systems, Inc. |
0a20de44 KG |
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 | ||
f16a1750 | 18 | #include "bfad_drv.h" |
a36c61f9 | 19 | #include "bfa_ioc.h" |
11189208 | 20 | #include "bfi_reg.h" |
a36c61f9 | 21 | #include "bfa_defs.h" |
0a20de44 KG |
22 | |
23 | BFA_TRC_FILE(CNA, IOC_CT); | |
24 | ||
f1d584d7 KG |
25 | #define bfa_ioc_ct_sync_pos(__ioc) \ |
26 | ((uint32_t) (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 | ||
0a20de44 KG |
34 | /* |
35 | * forward declarations | |
36 | */ | |
0a20de44 KG |
37 | static bfa_boolean_t bfa_ioc_ct_firmware_lock(struct bfa_ioc_s *ioc); |
38 | static void bfa_ioc_ct_firmware_unlock(struct bfa_ioc_s *ioc); | |
f1d584d7 | 39 | static void bfa_ioc_ct_notify_fail(struct bfa_ioc_s *ioc); |
0a20de44 | 40 | static void bfa_ioc_ct_ownership_reset(struct bfa_ioc_s *ioc); |
45d7f0cc | 41 | static bfa_boolean_t bfa_ioc_ct_sync_start(struct bfa_ioc_s *ioc); |
f1d584d7 KG |
42 | static void bfa_ioc_ct_sync_join(struct bfa_ioc_s *ioc); |
43 | static void bfa_ioc_ct_sync_leave(struct bfa_ioc_s *ioc); | |
44 | static void bfa_ioc_ct_sync_ack(struct bfa_ioc_s *ioc); | |
45 | static bfa_boolean_t bfa_ioc_ct_sync_complete(struct bfa_ioc_s *ioc); | |
c679b599 VMG |
46 | static void bfa_ioc_ct_set_cur_ioc_fwstate( |
47 | struct bfa_ioc_s *ioc, enum bfi_ioc_state fwstate); | |
48 | static enum bfi_ioc_state bfa_ioc_ct_get_cur_ioc_fwstate(struct bfa_ioc_s *ioc); | |
49 | static void bfa_ioc_ct_set_alt_ioc_fwstate( | |
50 | struct bfa_ioc_s *ioc, enum bfi_ioc_state fwstate); | |
51 | static enum bfi_ioc_state bfa_ioc_ct_get_alt_ioc_fwstate(struct bfa_ioc_s *ioc); | |
0a20de44 | 52 | |
52f94b6f | 53 | static struct bfa_ioc_hwif_s hwif_ct; |
11189208 | 54 | static struct bfa_ioc_hwif_s hwif_ct2; |
0a20de44 | 55 | |
5fbe25c7 | 56 | /* |
0a20de44 KG |
57 | * Return true if firmware of current driver matches the running firmware. |
58 | */ | |
59 | static bfa_boolean_t | |
60 | bfa_ioc_ct_firmware_lock(struct bfa_ioc_s *ioc) | |
61 | { | |
62 | enum bfi_ioc_state ioc_fwstate; | |
d1c61f8e | 63 | u32 usecnt; |
0a20de44 KG |
64 | struct bfi_ioc_image_hdr_s fwhdr; |
65 | ||
0a20de44 | 66 | bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg); |
53440260 | 67 | usecnt = readl(ioc->ioc_regs.ioc_usage_reg); |
0a20de44 | 68 | |
5fbe25c7 | 69 | /* |
0a20de44 KG |
70 | * If usage count is 0, always return TRUE. |
71 | */ | |
72 | if (usecnt == 0) { | |
53440260 | 73 | writel(1, ioc->ioc_regs.ioc_usage_reg); |
5a0adaed | 74 | readl(ioc->ioc_regs.ioc_usage_sem_reg); |
f7f73812 | 75 | writel(1, ioc->ioc_regs.ioc_usage_sem_reg); |
f1d584d7 | 76 | writel(0, ioc->ioc_regs.ioc_fail_sync); |
0a20de44 KG |
77 | bfa_trc(ioc, usecnt); |
78 | return BFA_TRUE; | |
79 | } | |
80 | ||
53440260 | 81 | ioc_fwstate = readl(ioc->ioc_regs.ioc_fwstate); |
0a20de44 KG |
82 | bfa_trc(ioc, ioc_fwstate); |
83 | ||
5fbe25c7 | 84 | /* |
0a20de44 KG |
85 | * Use count cannot be non-zero and chip in uninitialized state. |
86 | */ | |
d4b671c5 | 87 | WARN_ON(ioc_fwstate == BFI_IOC_UNINIT); |
0a20de44 | 88 | |
5fbe25c7 | 89 | /* |
0a20de44 KG |
90 | * Check if another driver with a different firmware is active |
91 | */ | |
92 | bfa_ioc_fwver_get(ioc, &fwhdr); | |
93 | if (!bfa_ioc_fwver_cmp(ioc, &fwhdr)) { | |
5a0adaed | 94 | readl(ioc->ioc_regs.ioc_usage_sem_reg); |
f7f73812 | 95 | writel(1, ioc->ioc_regs.ioc_usage_sem_reg); |
0a20de44 KG |
96 | bfa_trc(ioc, usecnt); |
97 | return BFA_FALSE; | |
98 | } | |
99 | ||
5fbe25c7 | 100 | /* |
0a20de44 KG |
101 | * Same firmware version. Increment the reference count. |
102 | */ | |
103 | usecnt++; | |
53440260 | 104 | writel(usecnt, ioc->ioc_regs.ioc_usage_reg); |
5a0adaed | 105 | readl(ioc->ioc_regs.ioc_usage_sem_reg); |
f7f73812 | 106 | writel(1, ioc->ioc_regs.ioc_usage_sem_reg); |
0a20de44 KG |
107 | bfa_trc(ioc, usecnt); |
108 | return BFA_TRUE; | |
109 | } | |
110 | ||
111 | static void | |
112 | bfa_ioc_ct_firmware_unlock(struct bfa_ioc_s *ioc) | |
113 | { | |
d1c61f8e | 114 | u32 usecnt; |
0a20de44 | 115 | |
5fbe25c7 | 116 | /* |
0a20de44 KG |
117 | * decrement usage count |
118 | */ | |
119 | bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg); | |
53440260 | 120 | usecnt = readl(ioc->ioc_regs.ioc_usage_reg); |
d4b671c5 | 121 | WARN_ON(usecnt <= 0); |
0a20de44 KG |
122 | |
123 | usecnt--; | |
53440260 | 124 | writel(usecnt, ioc->ioc_regs.ioc_usage_reg); |
0a20de44 KG |
125 | bfa_trc(ioc, usecnt); |
126 | ||
5a0adaed | 127 | readl(ioc->ioc_regs.ioc_usage_sem_reg); |
f7f73812 | 128 | writel(1, ioc->ioc_regs.ioc_usage_sem_reg); |
0a20de44 KG |
129 | } |
130 | ||
5fbe25c7 | 131 | /* |
0a20de44 KG |
132 | * Notify other functions on HB failure. |
133 | */ | |
134 | static void | |
f1d584d7 | 135 | bfa_ioc_ct_notify_fail(struct bfa_ioc_s *ioc) |
0a20de44 | 136 | { |
11189208 | 137 | if (bfa_ioc_is_cna(ioc)) { |
53440260 | 138 | writel(__FW_INIT_HALT_P, ioc->ioc_regs.ll_halt); |
f1d584d7 | 139 | writel(__FW_INIT_HALT_P, ioc->ioc_regs.alt_ll_halt); |
816e49b8 | 140 | /* Wait for halt to take effect */ |
53440260 | 141 | readl(ioc->ioc_regs.ll_halt); |
f1d584d7 | 142 | readl(ioc->ioc_regs.alt_ll_halt); |
816e49b8 | 143 | } else { |
11189208 | 144 | writel(~0U, ioc->ioc_regs.err_set); |
53440260 | 145 | readl(ioc->ioc_regs.err_set); |
816e49b8 | 146 | } |
0a20de44 KG |
147 | } |
148 | ||
5fbe25c7 | 149 | /* |
0a20de44 KG |
150 | * Host to LPU mailbox message addresses |
151 | */ | |
11189208 | 152 | static struct { u32 hfn_mbox, lpu_mbox, hfn_pgn; } ct_fnreg[] = { |
0a20de44 KG |
153 | { HOSTFN0_LPU_MBOX0_0, LPU_HOSTFN0_MBOX0_0, HOST_PAGE_NUM_FN0 }, |
154 | { HOSTFN1_LPU_MBOX0_8, LPU_HOSTFN1_MBOX0_8, HOST_PAGE_NUM_FN1 }, | |
155 | { HOSTFN2_LPU_MBOX0_0, LPU_HOSTFN2_MBOX0_0, HOST_PAGE_NUM_FN2 }, | |
156 | { HOSTFN3_LPU_MBOX0_8, LPU_HOSTFN3_MBOX0_8, HOST_PAGE_NUM_FN3 } | |
157 | }; | |
158 | ||
5fbe25c7 | 159 | /* |
0a20de44 KG |
160 | * Host <-> LPU mailbox command/status registers - port 0 |
161 | */ | |
11189208 KG |
162 | static struct { u32 hfn, lpu; } ct_p0reg[] = { |
163 | { HOSTFN0_LPU0_CMD_STAT, LPU0_HOSTFN0_CMD_STAT }, | |
164 | { HOSTFN1_LPU0_CMD_STAT, LPU0_HOSTFN1_CMD_STAT }, | |
165 | { HOSTFN2_LPU0_CMD_STAT, LPU0_HOSTFN2_CMD_STAT }, | |
166 | { HOSTFN3_LPU0_CMD_STAT, LPU0_HOSTFN3_CMD_STAT } | |
0a20de44 KG |
167 | }; |
168 | ||
5fbe25c7 | 169 | /* |
0a20de44 KG |
170 | * Host <-> LPU mailbox command/status registers - port 1 |
171 | */ | |
11189208 KG |
172 | static struct { u32 hfn, lpu; } ct_p1reg[] = { |
173 | { HOSTFN0_LPU1_CMD_STAT, LPU1_HOSTFN0_CMD_STAT }, | |
174 | { HOSTFN1_LPU1_CMD_STAT, LPU1_HOSTFN1_CMD_STAT }, | |
175 | { HOSTFN2_LPU1_CMD_STAT, LPU1_HOSTFN2_CMD_STAT }, | |
176 | { HOSTFN3_LPU1_CMD_STAT, LPU1_HOSTFN3_CMD_STAT } | |
177 | }; | |
178 | ||
8b070b4a KG |
179 | static struct { uint32_t hfn_mbox, lpu_mbox, hfn_pgn, hfn, lpu, lpu_read; } |
180 | ct2_reg[] = { | |
11189208 | 181 | { CT2_HOSTFN_LPU0_MBOX0, CT2_LPU0_HOSTFN_MBOX0, CT2_HOSTFN_PAGE_NUM, |
8b070b4a KG |
182 | CT2_HOSTFN_LPU0_CMD_STAT, CT2_LPU0_HOSTFN_CMD_STAT, |
183 | CT2_HOSTFN_LPU0_READ_STAT}, | |
11189208 | 184 | { CT2_HOSTFN_LPU1_MBOX0, CT2_LPU1_HOSTFN_MBOX0, CT2_HOSTFN_PAGE_NUM, |
8b070b4a KG |
185 | CT2_HOSTFN_LPU1_CMD_STAT, CT2_LPU1_HOSTFN_CMD_STAT, |
186 | CT2_HOSTFN_LPU1_READ_STAT}, | |
0a20de44 KG |
187 | }; |
188 | ||
189 | static void | |
190 | bfa_ioc_ct_reg_init(struct bfa_ioc_s *ioc) | |
191 | { | |
53440260 | 192 | void __iomem *rb; |
0a20de44 KG |
193 | int pcifn = bfa_ioc_pcifn(ioc); |
194 | ||
195 | rb = bfa_ioc_bar0(ioc); | |
196 | ||
11189208 KG |
197 | ioc->ioc_regs.hfn_mbox = rb + ct_fnreg[pcifn].hfn_mbox; |
198 | ioc->ioc_regs.lpu_mbox = rb + ct_fnreg[pcifn].lpu_mbox; | |
199 | ioc->ioc_regs.host_page_num_fn = rb + ct_fnreg[pcifn].hfn_pgn; | |
0a20de44 KG |
200 | |
201 | if (ioc->port_id == 0) { | |
202 | ioc->ioc_regs.heartbeat = rb + BFA_IOC0_HBEAT_REG; | |
203 | ioc->ioc_regs.ioc_fwstate = rb + BFA_IOC0_STATE_REG; | |
f1d584d7 | 204 | ioc->ioc_regs.alt_ioc_fwstate = rb + BFA_IOC1_STATE_REG; |
11189208 KG |
205 | ioc->ioc_regs.hfn_mbox_cmd = rb + ct_p0reg[pcifn].hfn; |
206 | ioc->ioc_regs.lpu_mbox_cmd = rb + ct_p0reg[pcifn].lpu; | |
0a20de44 | 207 | ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P0; |
f1d584d7 | 208 | ioc->ioc_regs.alt_ll_halt = rb + FW_INIT_HALT_P1; |
0a20de44 KG |
209 | } else { |
210 | ioc->ioc_regs.heartbeat = (rb + BFA_IOC1_HBEAT_REG); | |
211 | ioc->ioc_regs.ioc_fwstate = (rb + BFA_IOC1_STATE_REG); | |
f1d584d7 | 212 | ioc->ioc_regs.alt_ioc_fwstate = rb + BFA_IOC0_STATE_REG; |
11189208 KG |
213 | ioc->ioc_regs.hfn_mbox_cmd = rb + ct_p1reg[pcifn].hfn; |
214 | ioc->ioc_regs.lpu_mbox_cmd = rb + ct_p1reg[pcifn].lpu; | |
0a20de44 | 215 | ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P1; |
f1d584d7 | 216 | ioc->ioc_regs.alt_ll_halt = rb + FW_INIT_HALT_P0; |
0a20de44 KG |
217 | } |
218 | ||
219 | /* | |
220 | * PSS control registers | |
221 | */ | |
222 | ioc->ioc_regs.pss_ctl_reg = (rb + PSS_CTL_REG); | |
8b651b42 | 223 | ioc->ioc_regs.pss_err_status_reg = (rb + PSS_ERR_STATUS_REG); |
11189208 KG |
224 | ioc->ioc_regs.app_pll_fast_ctl_reg = (rb + APP_PLL_LCLK_CTL_REG); |
225 | ioc->ioc_regs.app_pll_slow_ctl_reg = (rb + APP_PLL_SCLK_CTL_REG); | |
0a20de44 KG |
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); | |
f1d584d7 | 234 | ioc->ioc_regs.ioc_fail_sync = (rb + BFA_IOC_FAIL_SYNC); |
0a20de44 | 235 | |
5fbe25c7 | 236 | /* |
0a20de44 KG |
237 | * sram memory access |
238 | */ | |
239 | ioc->ioc_regs.smem_page_start = (rb + PSS_SMEM_PAGE_START); | |
240 | ioc->ioc_regs.smem_pg0 = BFI_IOC_SMEM_PG0_CT; | |
816e49b8 KG |
241 | |
242 | /* | |
243 | * err set reg : for notification of hb failure in fcmode | |
244 | */ | |
245 | ioc->ioc_regs.err_set = (rb + ERR_SET_REG); | |
0a20de44 KG |
246 | } |
247 | ||
11189208 KG |
248 | static void |
249 | bfa_ioc_ct2_reg_init(struct bfa_ioc_s *ioc) | |
250 | { | |
251 | void __iomem *rb; | |
252 | int port = bfa_ioc_portid(ioc); | |
253 | ||
254 | rb = bfa_ioc_bar0(ioc); | |
255 | ||
256 | ioc->ioc_regs.hfn_mbox = rb + ct2_reg[port].hfn_mbox; | |
257 | ioc->ioc_regs.lpu_mbox = rb + ct2_reg[port].lpu_mbox; | |
258 | ioc->ioc_regs.host_page_num_fn = rb + ct2_reg[port].hfn_pgn; | |
259 | ioc->ioc_regs.hfn_mbox_cmd = rb + ct2_reg[port].hfn; | |
260 | ioc->ioc_regs.lpu_mbox_cmd = rb + ct2_reg[port].lpu; | |
8b070b4a | 261 | ioc->ioc_regs.lpu_read_stat = rb + ct2_reg[port].lpu_read; |
11189208 KG |
262 | |
263 | if (port == 0) { | |
264 | ioc->ioc_regs.heartbeat = rb + CT2_BFA_IOC0_HBEAT_REG; | |
265 | ioc->ioc_regs.ioc_fwstate = rb + CT2_BFA_IOC0_STATE_REG; | |
266 | ioc->ioc_regs.alt_ioc_fwstate = rb + CT2_BFA_IOC1_STATE_REG; | |
267 | ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P0; | |
268 | ioc->ioc_regs.alt_ll_halt = rb + FW_INIT_HALT_P1; | |
269 | } else { | |
270 | ioc->ioc_regs.heartbeat = (rb + CT2_BFA_IOC1_HBEAT_REG); | |
271 | ioc->ioc_regs.ioc_fwstate = (rb + CT2_BFA_IOC1_STATE_REG); | |
272 | ioc->ioc_regs.alt_ioc_fwstate = rb + CT2_BFA_IOC0_STATE_REG; | |
273 | ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P1; | |
274 | ioc->ioc_regs.alt_ll_halt = rb + FW_INIT_HALT_P0; | |
275 | } | |
276 | ||
277 | /* | |
278 | * PSS control registers | |
279 | */ | |
280 | ioc->ioc_regs.pss_ctl_reg = (rb + PSS_CTL_REG); | |
281 | ioc->ioc_regs.pss_err_status_reg = (rb + PSS_ERR_STATUS_REG); | |
282 | ioc->ioc_regs.app_pll_fast_ctl_reg = (rb + CT2_APP_PLL_LCLK_CTL_REG); | |
283 | ioc->ioc_regs.app_pll_slow_ctl_reg = (rb + CT2_APP_PLL_SCLK_CTL_REG); | |
284 | ||
285 | /* | |
286 | * IOC semaphore registers and serialization | |
287 | */ | |
288 | ioc->ioc_regs.ioc_sem_reg = (rb + CT2_HOST_SEM0_REG); | |
289 | ioc->ioc_regs.ioc_usage_sem_reg = (rb + CT2_HOST_SEM1_REG); | |
290 | ioc->ioc_regs.ioc_init_sem_reg = (rb + CT2_HOST_SEM2_REG); | |
775c7742 KG |
291 | ioc->ioc_regs.ioc_usage_reg = (rb + CT2_BFA_FW_USE_COUNT); |
292 | ioc->ioc_regs.ioc_fail_sync = (rb + CT2_BFA_IOC_FAIL_SYNC); | |
11189208 KG |
293 | |
294 | /* | |
295 | * sram memory access | |
296 | */ | |
297 | ioc->ioc_regs.smem_page_start = (rb + PSS_SMEM_PAGE_START); | |
298 | ioc->ioc_regs.smem_pg0 = BFI_IOC_SMEM_PG0_CT; | |
299 | ||
300 | /* | |
301 | * err set reg : for notification of hb failure in fcmode | |
302 | */ | |
303 | ioc->ioc_regs.err_set = (rb + ERR_SET_REG); | |
304 | } | |
305 | ||
5fbe25c7 | 306 | /* |
0a20de44 KG |
307 | * Initialize IOC to port mapping. |
308 | */ | |
309 | ||
310 | #define FNC_PERS_FN_SHIFT(__fn) ((__fn) * 8) | |
311 | static void | |
312 | bfa_ioc_ct_map_port(struct bfa_ioc_s *ioc) | |
313 | { | |
53440260 | 314 | void __iomem *rb = ioc->pcidev.pci_bar_kva; |
d1c61f8e | 315 | u32 r32; |
0a20de44 | 316 | |
5fbe25c7 | 317 | /* |
0a20de44 KG |
318 | * For catapult, base port id on personality register and IOC type |
319 | */ | |
53440260 | 320 | r32 = readl(rb + FNC_PERS_REG); |
0a20de44 KG |
321 | r32 >>= FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc)); |
322 | ioc->port_id = (r32 & __F0_PORT_MAP_MK) >> __F0_PORT_MAP_SH; | |
323 | ||
324 | bfa_trc(ioc, bfa_ioc_pcifn(ioc)); | |
325 | bfa_trc(ioc, ioc->port_id); | |
326 | } | |
327 | ||
11189208 KG |
328 | static void |
329 | bfa_ioc_ct2_map_port(struct bfa_ioc_s *ioc) | |
330 | { | |
5a0adaed KG |
331 | void __iomem *rb = ioc->pcidev.pci_bar_kva; |
332 | u32 r32; | |
333 | ||
334 | r32 = readl(rb + CT2_HOSTFN_PERSONALITY0); | |
335 | ioc->port_id = ((r32 & __FC_LL_PORT_MAP__MK) >> __FC_LL_PORT_MAP__SH); | |
11189208 KG |
336 | |
337 | bfa_trc(ioc, bfa_ioc_pcifn(ioc)); | |
338 | bfa_trc(ioc, ioc->port_id); | |
339 | } | |
340 | ||
5fbe25c7 | 341 | /* |
0a20de44 KG |
342 | * Set interrupt mode for a function: INTX or MSIX |
343 | */ | |
344 | static void | |
345 | bfa_ioc_ct_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix) | |
346 | { | |
53440260 | 347 | void __iomem *rb = ioc->pcidev.pci_bar_kva; |
d1c61f8e | 348 | u32 r32, mode; |
0a20de44 | 349 | |
53440260 | 350 | r32 = readl(rb + FNC_PERS_REG); |
0a20de44 KG |
351 | bfa_trc(ioc, r32); |
352 | ||
353 | mode = (r32 >> FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc))) & | |
354 | __F0_INTX_STATUS; | |
355 | ||
5fbe25c7 | 356 | /* |
0a20de44 KG |
357 | * If already in desired mode, do not change anything |
358 | */ | |
11189208 | 359 | if ((!msix && mode) || (msix && !mode)) |
0a20de44 KG |
360 | return; |
361 | ||
362 | if (msix) | |
363 | mode = __F0_INTX_STATUS_MSIX; | |
364 | else | |
365 | mode = __F0_INTX_STATUS_INTA; | |
366 | ||
367 | r32 &= ~(__F0_INTX_STATUS << FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc))); | |
368 | r32 |= (mode << FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc))); | |
369 | bfa_trc(ioc, r32); | |
370 | ||
53440260 | 371 | writel(r32, rb + FNC_PERS_REG); |
0a20de44 KG |
372 | } |
373 | ||
8b070b4a KG |
374 | bfa_boolean_t |
375 | bfa_ioc_ct2_lpu_read_stat(struct bfa_ioc_s *ioc) | |
376 | { | |
377 | u32 r32; | |
378 | ||
379 | r32 = readl(ioc->ioc_regs.lpu_read_stat); | |
380 | if (r32) { | |
381 | writel(1, ioc->ioc_regs.lpu_read_stat); | |
382 | return BFA_TRUE; | |
383 | } | |
384 | ||
385 | return BFA_FALSE; | |
386 | } | |
387 | ||
5fbe25c7 | 388 | /* |
a36c61f9 KG |
389 | * Cleanup hw semaphore and usecnt registers |
390 | */ | |
391 | static void | |
392 | bfa_ioc_ct_ownership_reset(struct bfa_ioc_s *ioc) | |
0a20de44 | 393 | { |
a36c61f9 | 394 | |
7ac83b1f KG |
395 | bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg); |
396 | writel(0, ioc->ioc_regs.ioc_usage_reg); | |
397 | readl(ioc->ioc_regs.ioc_usage_sem_reg); | |
398 | writel(1, ioc->ioc_regs.ioc_usage_sem_reg); | |
0a20de44 | 399 | |
7ac83b1f | 400 | writel(0, ioc->ioc_regs.ioc_fail_sync); |
0a20de44 | 401 | /* |
a36c61f9 KG |
402 | * Read the hw sem reg to make sure that it is locked |
403 | * before we clear it. If it is not locked, writing 1 | |
404 | * will lock it instead of clearing it. | |
0a20de44 | 405 | */ |
53440260 | 406 | readl(ioc->ioc_regs.ioc_sem_reg); |
f7f73812 | 407 | writel(1, ioc->ioc_regs.ioc_sem_reg); |
a36c61f9 KG |
408 | } |
409 | ||
45d7f0cc JH |
410 | static bfa_boolean_t |
411 | bfa_ioc_ct_sync_start(struct bfa_ioc_s *ioc) | |
412 | { | |
413 | uint32_t r32 = readl(ioc->ioc_regs.ioc_fail_sync); | |
414 | uint32_t sync_reqd = bfa_ioc_ct_get_sync_reqd(r32); | |
415 | ||
416 | /* | |
417 | * Driver load time. If the sync required bit for this PCI fn | |
418 | * is set, it is due to an unclean exit by the driver for this | |
419 | * PCI fn in the previous incarnation. Whoever comes here first | |
420 | * should clean it up, no matter which PCI fn. | |
421 | */ | |
422 | ||
423 | if (sync_reqd & bfa_ioc_ct_sync_pos(ioc)) { | |
424 | writel(0, ioc->ioc_regs.ioc_fail_sync); | |
425 | writel(1, ioc->ioc_regs.ioc_usage_reg); | |
426 | writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate); | |
427 | writel(BFI_IOC_UNINIT, ioc->ioc_regs.alt_ioc_fwstate); | |
428 | return BFA_TRUE; | |
429 | } | |
430 | ||
431 | return bfa_ioc_ct_sync_complete(ioc); | |
432 | } | |
433 | ||
8f4bfadd | 434 | /* |
f1d584d7 KG |
435 | * Synchronized IOC failure processing routines |
436 | */ | |
437 | static void | |
438 | bfa_ioc_ct_sync_join(struct bfa_ioc_s *ioc) | |
439 | { | |
440 | uint32_t r32 = readl(ioc->ioc_regs.ioc_fail_sync); | |
441 | uint32_t sync_pos = bfa_ioc_ct_sync_reqd_pos(ioc); | |
442 | ||
443 | writel((r32 | sync_pos), ioc->ioc_regs.ioc_fail_sync); | |
444 | } | |
a36c61f9 | 445 | |
f1d584d7 KG |
446 | static void |
447 | bfa_ioc_ct_sync_leave(struct bfa_ioc_s *ioc) | |
448 | { | |
449 | uint32_t r32 = readl(ioc->ioc_regs.ioc_fail_sync); | |
450 | uint32_t sync_msk = bfa_ioc_ct_sync_reqd_pos(ioc) | | |
451 | bfa_ioc_ct_sync_pos(ioc); | |
452 | ||
453 | writel((r32 & ~sync_msk), ioc->ioc_regs.ioc_fail_sync); | |
454 | } | |
455 | ||
456 | static void | |
457 | bfa_ioc_ct_sync_ack(struct bfa_ioc_s *ioc) | |
458 | { | |
459 | uint32_t r32 = readl(ioc->ioc_regs.ioc_fail_sync); | |
460 | ||
461 | writel((r32 | bfa_ioc_ct_sync_pos(ioc)), | |
462 | ioc->ioc_regs.ioc_fail_sync); | |
463 | } | |
464 | ||
465 | static bfa_boolean_t | |
466 | bfa_ioc_ct_sync_complete(struct bfa_ioc_s *ioc) | |
467 | { | |
468 | uint32_t r32 = readl(ioc->ioc_regs.ioc_fail_sync); | |
469 | uint32_t sync_reqd = bfa_ioc_ct_get_sync_reqd(r32); | |
470 | uint32_t sync_ackd = bfa_ioc_ct_get_sync_ackd(r32); | |
471 | uint32_t tmp_ackd; | |
472 | ||
473 | if (sync_ackd == 0) | |
474 | return BFA_TRUE; | |
475 | ||
8f4bfadd | 476 | /* |
f1d584d7 KG |
477 | * The check below is to see whether any other PCI fn |
478 | * has reinitialized the ASIC (reset sync_ackd bits) | |
479 | * and failed again while this IOC was waiting for hw | |
480 | * semaphore (in bfa_iocpf_sm_semwait()). | |
481 | */ | |
482 | tmp_ackd = sync_ackd; | |
483 | if ((sync_reqd & bfa_ioc_ct_sync_pos(ioc)) && | |
484 | !(sync_ackd & bfa_ioc_ct_sync_pos(ioc))) | |
485 | sync_ackd |= bfa_ioc_ct_sync_pos(ioc); | |
486 | ||
487 | if (sync_reqd == sync_ackd) { | |
488 | writel(bfa_ioc_ct_clear_sync_ackd(r32), | |
489 | ioc->ioc_regs.ioc_fail_sync); | |
490 | writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate); | |
491 | writel(BFI_IOC_FAIL, ioc->ioc_regs.alt_ioc_fwstate); | |
492 | return BFA_TRUE; | |
493 | } | |
494 | ||
8f4bfadd | 495 | /* |
f1d584d7 KG |
496 | * If another PCI fn reinitialized and failed again while |
497 | * this IOC was waiting for hw sem, the sync_ackd bit for | |
498 | * this IOC need to be set again to allow reinitialization. | |
499 | */ | |
500 | if (tmp_ackd != sync_ackd) | |
501 | writel((r32 | sync_ackd), ioc->ioc_regs.ioc_fail_sync); | |
502 | ||
503 | return BFA_FALSE; | |
504 | } | |
a36c61f9 | 505 | |
11189208 KG |
506 | /** |
507 | * Called from bfa_ioc_attach() to map asic specific calls. | |
508 | */ | |
509 | static void | |
510 | bfa_ioc_set_ctx_hwif(struct bfa_ioc_s *ioc, struct bfa_ioc_hwif_s *hwif) | |
511 | { | |
512 | hwif->ioc_firmware_lock = bfa_ioc_ct_firmware_lock; | |
513 | hwif->ioc_firmware_unlock = bfa_ioc_ct_firmware_unlock; | |
514 | hwif->ioc_notify_fail = bfa_ioc_ct_notify_fail; | |
515 | hwif->ioc_ownership_reset = bfa_ioc_ct_ownership_reset; | |
516 | hwif->ioc_sync_start = bfa_ioc_ct_sync_start; | |
517 | hwif->ioc_sync_join = bfa_ioc_ct_sync_join; | |
518 | hwif->ioc_sync_leave = bfa_ioc_ct_sync_leave; | |
519 | hwif->ioc_sync_ack = bfa_ioc_ct_sync_ack; | |
520 | hwif->ioc_sync_complete = bfa_ioc_ct_sync_complete; | |
c679b599 VMG |
521 | hwif->ioc_set_fwstate = bfa_ioc_ct_set_cur_ioc_fwstate; |
522 | hwif->ioc_get_fwstate = bfa_ioc_ct_get_cur_ioc_fwstate; | |
523 | hwif->ioc_set_alt_fwstate = bfa_ioc_ct_set_alt_ioc_fwstate; | |
524 | hwif->ioc_get_alt_fwstate = bfa_ioc_ct_get_alt_ioc_fwstate; | |
11189208 KG |
525 | } |
526 | ||
527 | /** | |
528 | * Called from bfa_ioc_attach() to map asic specific calls. | |
529 | */ | |
530 | void | |
531 | bfa_ioc_set_ct_hwif(struct bfa_ioc_s *ioc) | |
532 | { | |
533 | bfa_ioc_set_ctx_hwif(ioc, &hwif_ct); | |
534 | ||
535 | hwif_ct.ioc_pll_init = bfa_ioc_ct_pll_init; | |
536 | hwif_ct.ioc_reg_init = bfa_ioc_ct_reg_init; | |
537 | hwif_ct.ioc_map_port = bfa_ioc_ct_map_port; | |
538 | hwif_ct.ioc_isr_mode_set = bfa_ioc_ct_isr_mode_set; | |
539 | ioc->ioc_hwif = &hwif_ct; | |
540 | } | |
541 | ||
542 | /** | |
543 | * Called from bfa_ioc_attach() to map asic specific calls. | |
544 | */ | |
545 | void | |
546 | bfa_ioc_set_ct2_hwif(struct bfa_ioc_s *ioc) | |
547 | { | |
548 | bfa_ioc_set_ctx_hwif(ioc, &hwif_ct2); | |
549 | ||
550 | hwif_ct2.ioc_pll_init = bfa_ioc_ct2_pll_init; | |
551 | hwif_ct2.ioc_reg_init = bfa_ioc_ct2_reg_init; | |
552 | hwif_ct2.ioc_map_port = bfa_ioc_ct2_map_port; | |
8b070b4a | 553 | hwif_ct2.ioc_lpu_read_stat = bfa_ioc_ct2_lpu_read_stat; |
11189208 KG |
554 | hwif_ct2.ioc_isr_mode_set = NULL; |
555 | ioc->ioc_hwif = &hwif_ct2; | |
556 | } | |
557 | ||
a36c61f9 | 558 | /* |
3fd45980 | 559 | * Workaround for MSI-X resource allocation for catapult-2 with no asic block |
a36c61f9 | 560 | */ |
3fd45980 | 561 | #define HOSTFN_MSIX_DEFAULT 64 |
10a07379 | 562 | #define HOSTFN_MSIX_VT_INDEX_MBOX_ERR 0x30138 |
11189208 KG |
563 | #define HOSTFN_MSIX_VT_OFST_NUMVT 0x3013c |
564 | #define __MSIX_VT_NUMVT__MK 0x003ff800 | |
565 | #define __MSIX_VT_NUMVT__SH 11 | |
566 | #define __MSIX_VT_NUMVT_(_v) ((_v) << __MSIX_VT_NUMVT__SH) | |
10a07379 | 567 | #define __MSIX_VT_OFST_ 0x000007ff |
11189208 KG |
568 | void |
569 | bfa_ioc_ct2_poweron(struct bfa_ioc_s *ioc) | |
a36c61f9 | 570 | { |
11189208 KG |
571 | void __iomem *rb = ioc->pcidev.pci_bar_kva; |
572 | u32 r32; | |
a36c61f9 | 573 | |
11189208 | 574 | r32 = readl(rb + HOSTFN_MSIX_VT_OFST_NUMVT); |
10a07379 KG |
575 | if (r32 & __MSIX_VT_NUMVT__MK) { |
576 | writel(r32 & __MSIX_VT_OFST_, | |
577 | rb + HOSTFN_MSIX_VT_INDEX_MBOX_ERR); | |
11189208 | 578 | return; |
10a07379 | 579 | } |
11189208 KG |
580 | |
581 | writel(__MSIX_VT_NUMVT_(HOSTFN_MSIX_DEFAULT - 1) | | |
582 | HOSTFN_MSIX_DEFAULT * bfa_ioc_pcifn(ioc), | |
583 | rb + HOSTFN_MSIX_VT_OFST_NUMVT); | |
10a07379 KG |
584 | writel(HOSTFN_MSIX_DEFAULT * bfa_ioc_pcifn(ioc), |
585 | rb + HOSTFN_MSIX_VT_INDEX_MBOX_ERR); | |
a36c61f9 KG |
586 | } |
587 | ||
588 | bfa_status_t | |
11189208 | 589 | bfa_ioc_ct_pll_init(void __iomem *rb, enum bfi_asic_mode mode) |
a36c61f9 KG |
590 | { |
591 | u32 pll_sclk, pll_fclk, r32; | |
11189208 KG |
592 | bfa_boolean_t fcmode = (mode == BFI_ASIC_MODE_FC); |
593 | ||
594 | pll_sclk = __APP_PLL_SCLK_LRESETN | __APP_PLL_SCLK_ENARST | | |
595 | __APP_PLL_SCLK_RSEL200500 | __APP_PLL_SCLK_P0_1(3U) | | |
596 | __APP_PLL_SCLK_JITLMT0_1(3U) | | |
597 | __APP_PLL_SCLK_CNTLMT0_1(1U); | |
598 | pll_fclk = __APP_PLL_LCLK_LRESETN | __APP_PLL_LCLK_ENARST | | |
599 | __APP_PLL_LCLK_RSEL200500 | __APP_PLL_LCLK_P0_1(3U) | | |
600 | __APP_PLL_LCLK_JITLMT0_1(3U) | | |
601 | __APP_PLL_LCLK_CNTLMT0_1(1U); | |
0a20de44 | 602 | |
a36c61f9 | 603 | if (fcmode) { |
53440260 JH |
604 | writel(0, (rb + OP_MODE)); |
605 | writel(__APP_EMS_CMLCKSEL | __APP_EMS_REFCKBUFEN2 | | |
606 | __APP_EMS_CHANNEL_SEL, (rb + ETH_MAC_SER_REG)); | |
0a20de44 | 607 | } else { |
53440260 JH |
608 | writel(__GLOBAL_FCOE_MODE, (rb + OP_MODE)); |
609 | writel(__APP_EMS_REFCKBUFEN1, (rb + ETH_MAC_SER_REG)); | |
0a20de44 | 610 | } |
53440260 JH |
611 | writel(BFI_IOC_UNINIT, (rb + BFA_IOC0_STATE_REG)); |
612 | writel(BFI_IOC_UNINIT, (rb + BFA_IOC1_STATE_REG)); | |
613 | writel(0xffffffffU, (rb + HOSTFN0_INT_MSK)); | |
614 | writel(0xffffffffU, (rb + HOSTFN1_INT_MSK)); | |
615 | writel(0xffffffffU, (rb + HOSTFN0_INT_STATUS)); | |
616 | writel(0xffffffffU, (rb + HOSTFN1_INT_STATUS)); | |
617 | writel(0xffffffffU, (rb + HOSTFN0_INT_MSK)); | |
618 | writel(0xffffffffU, (rb + HOSTFN1_INT_MSK)); | |
11189208 KG |
619 | writel(pll_sclk | __APP_PLL_SCLK_LOGIC_SOFT_RESET, |
620 | rb + APP_PLL_SCLK_CTL_REG); | |
621 | writel(pll_fclk | __APP_PLL_LCLK_LOGIC_SOFT_RESET, | |
622 | rb + APP_PLL_LCLK_CTL_REG); | |
623 | writel(pll_sclk | __APP_PLL_SCLK_LOGIC_SOFT_RESET | | |
624 | __APP_PLL_SCLK_ENABLE, rb + APP_PLL_SCLK_CTL_REG); | |
625 | writel(pll_fclk | __APP_PLL_LCLK_LOGIC_SOFT_RESET | | |
626 | __APP_PLL_LCLK_ENABLE, rb + APP_PLL_LCLK_CTL_REG); | |
53440260 | 627 | readl(rb + HOSTFN0_INT_MSK); |
6a18b167 | 628 | udelay(2000); |
53440260 JH |
629 | writel(0xffffffffU, (rb + HOSTFN0_INT_STATUS)); |
630 | writel(0xffffffffU, (rb + HOSTFN1_INT_STATUS)); | |
11189208 KG |
631 | writel(pll_sclk | __APP_PLL_SCLK_ENABLE, rb + APP_PLL_SCLK_CTL_REG); |
632 | writel(pll_fclk | __APP_PLL_LCLK_ENABLE, rb + APP_PLL_LCLK_CTL_REG); | |
633 | ||
a36c61f9 | 634 | if (!fcmode) { |
53440260 JH |
635 | writel(__PMM_1T_RESET_P, (rb + PMM_1T_RESET_REG_P0)); |
636 | writel(__PMM_1T_RESET_P, (rb + PMM_1T_RESET_REG_P1)); | |
df2a52a6 | 637 | } |
53440260 | 638 | r32 = readl((rb + PSS_CTL_REG)); |
df2a52a6 | 639 | r32 &= ~__PSS_LMEM_RESET; |
53440260 | 640 | writel(r32, (rb + PSS_CTL_REG)); |
6a18b167 | 641 | udelay(1000); |
a36c61f9 | 642 | if (!fcmode) { |
53440260 JH |
643 | writel(0, (rb + PMM_1T_RESET_REG_P0)); |
644 | writel(0, (rb + PMM_1T_RESET_REG_P1)); | |
df2a52a6 JH |
645 | } |
646 | ||
53440260 | 647 | writel(__EDRAM_BISTR_START, (rb + MBIST_CTL_REG)); |
6a18b167 | 648 | udelay(1000); |
53440260 JH |
649 | r32 = readl((rb + MBIST_STAT_REG)); |
650 | writel(0, (rb + MBIST_CTL_REG)); | |
0a20de44 KG |
651 | return BFA_STATUS_OK; |
652 | } | |
11189208 | 653 | |
11189208 | 654 | static void |
10a07379 | 655 | bfa_ioc_ct2_sclk_init(void __iomem *rb) |
11189208 KG |
656 | { |
657 | u32 r32; | |
658 | ||
659 | /* | |
660 | * put s_clk PLL and PLL FSM in reset | |
661 | */ | |
662 | r32 = readl((rb + CT2_APP_PLL_SCLK_CTL_REG)); | |
663 | r32 &= ~(__APP_PLL_SCLK_ENABLE | __APP_PLL_SCLK_LRESETN); | |
664 | r32 |= (__APP_PLL_SCLK_ENARST | __APP_PLL_SCLK_BYPASS | | |
665 | __APP_PLL_SCLK_LOGIC_SOFT_RESET); | |
666 | writel(r32, (rb + CT2_APP_PLL_SCLK_CTL_REG)); | |
667 | ||
668 | /* | |
10a07379 KG |
669 | * Ignore mode and program for the max clock (which is FC16) |
670 | * Firmware/NFC will do the PLL init appropiately | |
11189208 KG |
671 | */ |
672 | r32 = readl((rb + CT2_APP_PLL_SCLK_CTL_REG)); | |
673 | r32 &= ~(__APP_PLL_SCLK_REFCLK_SEL | __APP_PLL_SCLK_CLK_DIV2); | |
10a07379 | 674 | writel(r32, (rb + CT2_APP_PLL_SCLK_CTL_REG)); |
11189208 KG |
675 | |
676 | /* | |
775c7742 | 677 | * while doing PLL init dont clock gate ethernet subsystem |
11189208 | 678 | */ |
775c7742 KG |
679 | r32 = readl((rb + CT2_CHIP_MISC_PRG)); |
680 | writel(r32 | __ETH_CLK_ENABLE_PORT0, (rb + CT2_CHIP_MISC_PRG)); | |
11189208 | 681 | |
775c7742 KG |
682 | r32 = readl((rb + CT2_PCIE_MISC_REG)); |
683 | writel(r32 | __ETH_CLK_ENABLE_PORT1, (rb + CT2_PCIE_MISC_REG)); | |
11189208 KG |
684 | |
685 | /* | |
686 | * set sclk value | |
687 | */ | |
688 | r32 = readl((rb + CT2_APP_PLL_SCLK_CTL_REG)); | |
689 | r32 &= (__P_SCLK_PLL_LOCK | __APP_PLL_SCLK_REFCLK_SEL | | |
690 | __APP_PLL_SCLK_CLK_DIV2); | |
691 | writel(r32 | 0x1061731b, (rb + CT2_APP_PLL_SCLK_CTL_REG)); | |
692 | ||
693 | /* | |
694 | * poll for s_clk lock or delay 1ms | |
695 | */ | |
696 | udelay(1000); | |
11189208 KG |
697 | } |
698 | ||
699 | static void | |
10a07379 | 700 | bfa_ioc_ct2_lclk_init(void __iomem *rb) |
11189208 KG |
701 | { |
702 | u32 r32; | |
703 | ||
704 | /* | |
705 | * put l_clk PLL and PLL FSM in reset | |
706 | */ | |
707 | r32 = readl((rb + CT2_APP_PLL_LCLK_CTL_REG)); | |
708 | r32 &= ~(__APP_PLL_LCLK_ENABLE | __APP_PLL_LCLK_LRESETN); | |
709 | r32 |= (__APP_PLL_LCLK_ENARST | __APP_PLL_LCLK_BYPASS | | |
710 | __APP_PLL_LCLK_LOGIC_SOFT_RESET); | |
711 | writel(r32, (rb + CT2_APP_PLL_LCLK_CTL_REG)); | |
712 | ||
713 | /* | |
10a07379 | 714 | * set LPU speed (set for FC16 which will work for other modes) |
11189208 KG |
715 | */ |
716 | r32 = readl((rb + CT2_CHIP_MISC_PRG)); | |
10a07379 | 717 | writel(r32, (rb + CT2_CHIP_MISC_PRG)); |
11189208 KG |
718 | |
719 | /* | |
10a07379 | 720 | * set LPU half speed (set for FC16 which will work for other modes) |
11189208 KG |
721 | */ |
722 | r32 = readl((rb + CT2_APP_PLL_LCLK_CTL_REG)); | |
10a07379 | 723 | writel(r32, (rb + CT2_APP_PLL_LCLK_CTL_REG)); |
11189208 KG |
724 | |
725 | /* | |
10a07379 | 726 | * set lclk for mode (set for FC16) |
11189208 KG |
727 | */ |
728 | r32 = readl((rb + CT2_APP_PLL_LCLK_CTL_REG)); | |
729 | r32 &= (__P_LCLK_PLL_LOCK | __APP_LPUCLK_HALFSPEED); | |
10a07379 | 730 | r32 |= 0x20c1731b; |
11189208 KG |
731 | writel(r32, (rb + CT2_APP_PLL_LCLK_CTL_REG)); |
732 | ||
733 | /* | |
734 | * poll for s_clk lock or delay 1ms | |
735 | */ | |
736 | udelay(1000); | |
11189208 KG |
737 | } |
738 | ||
739 | static void | |
10a07379 | 740 | bfa_ioc_ct2_mem_init(void __iomem *rb) |
11189208 | 741 | { |
11189208 KG |
742 | u32 r32; |
743 | ||
11189208 KG |
744 | r32 = readl((rb + PSS_CTL_REG)); |
745 | r32 &= ~__PSS_LMEM_RESET; | |
746 | writel(r32, (rb + PSS_CTL_REG)); | |
747 | udelay(1000); | |
748 | ||
749 | writel(__EDRAM_BISTR_START, (rb + CT2_MBIST_CTL_REG)); | |
750 | udelay(1000); | |
751 | writel(0, (rb + CT2_MBIST_CTL_REG)); | |
752 | } | |
753 | ||
10a07379 KG |
754 | void |
755 | bfa_ioc_ct2_mac_reset(void __iomem *rb) | |
756 | { | |
10a07379 KG |
757 | /* put port0, port1 MAC & AHB in reset */ |
758 | writel((__CSI_MAC_RESET | __CSI_MAC_AHB_RESET), | |
759 | rb + CT2_CSI_MAC_CONTROL_REG(0)); | |
760 | writel((__CSI_MAC_RESET | __CSI_MAC_AHB_RESET), | |
761 | rb + CT2_CSI_MAC_CONTROL_REG(1)); | |
762 | } | |
763 | ||
227fab90 KG |
764 | static void |
765 | bfa_ioc_ct2_enable_flash(void __iomem *rb) | |
766 | { | |
767 | u32 r32; | |
768 | ||
769 | r32 = readl((rb + PSS_GPIO_OUT_REG)); | |
770 | writel(r32 & ~1, (rb + PSS_GPIO_OUT_REG)); | |
771 | r32 = readl((rb + PSS_GPIO_OE_REG)); | |
772 | writel(r32 | 1, (rb + PSS_GPIO_OE_REG)); | |
773 | } | |
774 | ||
10a07379 | 775 | #define CT2_NFC_MAX_DELAY 1000 |
227fab90 KG |
776 | #define CT2_NFC_PAUSE_MAX_DELAY 4000 |
777 | #define CT2_NFC_VER_VALID 0x147 | |
778 | #define CT2_NFC_STATE_RUNNING 0x20000001 | |
a6b963db KG |
779 | #define BFA_IOC_PLL_POLL 1000000 |
780 | ||
781 | static bfa_boolean_t | |
782 | bfa_ioc_ct2_nfc_halted(void __iomem *rb) | |
783 | { | |
784 | u32 r32; | |
785 | ||
786 | r32 = readl(rb + CT2_NFC_CSR_SET_REG); | |
787 | if (r32 & __NFC_CONTROLLER_HALTED) | |
788 | return BFA_TRUE; | |
789 | ||
790 | return BFA_FALSE; | |
791 | } | |
792 | ||
227fab90 KG |
793 | static void |
794 | bfa_ioc_ct2_nfc_halt(void __iomem *rb) | |
795 | { | |
796 | int i; | |
797 | ||
798 | writel(__HALT_NFC_CONTROLLER, rb + CT2_NFC_CSR_SET_REG); | |
799 | for (i = 0; i < CT2_NFC_MAX_DELAY; i++) { | |
800 | if (bfa_ioc_ct2_nfc_halted(rb)) | |
801 | break; | |
802 | udelay(1000); | |
803 | } | |
804 | WARN_ON(!bfa_ioc_ct2_nfc_halted(rb)); | |
805 | } | |
806 | ||
a6b963db KG |
807 | static void |
808 | bfa_ioc_ct2_nfc_resume(void __iomem *rb) | |
809 | { | |
810 | u32 r32; | |
811 | int i; | |
812 | ||
813 | writel(__HALT_NFC_CONTROLLER, rb + CT2_NFC_CSR_CLR_REG); | |
814 | for (i = 0; i < CT2_NFC_MAX_DELAY; i++) { | |
815 | r32 = readl(rb + CT2_NFC_CSR_SET_REG); | |
816 | if (!(r32 & __NFC_CONTROLLER_HALTED)) | |
817 | return; | |
818 | udelay(1000); | |
819 | } | |
820 | WARN_ON(1); | |
821 | } | |
822 | ||
227fab90 KG |
823 | static void |
824 | bfa_ioc_ct2_clk_reset(void __iomem *rb) | |
11189208 | 825 | { |
227fab90 | 826 | u32 r32; |
8b070b4a | 827 | |
227fab90 KG |
828 | bfa_ioc_ct2_sclk_init(rb); |
829 | bfa_ioc_ct2_lclk_init(rb); | |
a6b963db | 830 | |
227fab90 KG |
831 | /* |
832 | * release soft reset on s_clk & l_clk | |
833 | */ | |
834 | r32 = readl((rb + CT2_APP_PLL_SCLK_CTL_REG)); | |
835 | writel(r32 & ~__APP_PLL_SCLK_LOGIC_SOFT_RESET, | |
836 | (rb + CT2_APP_PLL_SCLK_CTL_REG)); | |
a6b963db | 837 | |
227fab90 KG |
838 | r32 = readl((rb + CT2_APP_PLL_LCLK_CTL_REG)); |
839 | writel(r32 & ~__APP_PLL_LCLK_LOGIC_SOFT_RESET, | |
840 | (rb + CT2_APP_PLL_LCLK_CTL_REG)); | |
a6b963db | 841 | |
227fab90 | 842 | } |
a6b963db | 843 | |
227fab90 KG |
844 | static void |
845 | bfa_ioc_ct2_nfc_clk_reset(void __iomem *rb) | |
846 | { | |
847 | u32 r32, i; | |
a6b963db | 848 | |
227fab90 KG |
849 | r32 = readl((rb + PSS_CTL_REG)); |
850 | r32 |= (__PSS_LPU0_RESET | __PSS_LPU1_RESET); | |
851 | writel(r32, (rb + PSS_CTL_REG)); | |
852 | ||
853 | writel(__RESET_AND_START_SCLK_LCLK_PLLS, rb + CT2_CSI_FW_CTL_SET_REG); | |
854 | ||
855 | for (i = 0; i < BFA_IOC_PLL_POLL; i++) { | |
856 | r32 = readl(rb + CT2_NFC_FLASH_STS_REG); | |
857 | ||
858 | if ((r32 & __FLASH_PLL_INIT_AND_RESET_IN_PROGRESS)) | |
859 | break; | |
860 | } | |
861 | WARN_ON(!(r32 & __FLASH_PLL_INIT_AND_RESET_IN_PROGRESS)); | |
862 | ||
863 | for (i = 0; i < BFA_IOC_PLL_POLL; i++) { | |
864 | r32 = readl(rb + CT2_NFC_FLASH_STS_REG); | |
865 | ||
866 | if (!(r32 & __FLASH_PLL_INIT_AND_RESET_IN_PROGRESS)) | |
867 | break; | |
868 | } | |
869 | WARN_ON((r32 & __FLASH_PLL_INIT_AND_RESET_IN_PROGRESS)); | |
870 | ||
871 | r32 = readl(rb + CT2_CSI_FW_CTL_REG); | |
872 | WARN_ON((r32 & __RESET_AND_START_SCLK_LCLK_PLLS)); | |
873 | } | |
874 | ||
875 | static void | |
876 | bfa_ioc_ct2_wait_till_nfc_running(void __iomem *rb) | |
877 | { | |
878 | u32 r32; | |
879 | int i; | |
a6b963db | 880 | |
227fab90 KG |
881 | if (bfa_ioc_ct2_nfc_halted(rb)) |
882 | bfa_ioc_ct2_nfc_resume(rb); | |
883 | for (i = 0; i < CT2_NFC_PAUSE_MAX_DELAY; i++) { | |
884 | r32 = readl(rb + CT2_NFC_STS_REG); | |
885 | if (r32 == CT2_NFC_STATE_RUNNING) | |
886 | return; | |
a6b963db | 887 | udelay(1000); |
227fab90 | 888 | } |
a6b963db | 889 | |
227fab90 KG |
890 | r32 = readl(rb + CT2_NFC_STS_REG); |
891 | WARN_ON(!(r32 == CT2_NFC_STATE_RUNNING)); | |
892 | } | |
8b070b4a | 893 | |
227fab90 KG |
894 | bfa_status_t |
895 | bfa_ioc_ct2_pll_init(void __iomem *rb, enum bfi_asic_mode mode) | |
896 | { | |
897 | u32 wgn, r32, nfc_ver; | |
a6b963db | 898 | |
227fab90 | 899 | wgn = readl(rb + CT2_WGN_STATUS); |
a6b963db | 900 | |
227fab90 | 901 | if (wgn == (__WGN_READY | __GLBL_PF_VF_CFG_RDY)) { |
a6b963db | 902 | /* |
227fab90 | 903 | * If flash is corrupted, enable flash explicitly |
a6b963db | 904 | */ |
227fab90 KG |
905 | bfa_ioc_ct2_clk_reset(rb); |
906 | bfa_ioc_ct2_enable_flash(rb); | |
11189208 | 907 | |
227fab90 KG |
908 | bfa_ioc_ct2_mac_reset(rb); |
909 | ||
910 | bfa_ioc_ct2_clk_reset(rb); | |
911 | bfa_ioc_ct2_enable_flash(rb); | |
912 | ||
913 | } else { | |
914 | nfc_ver = readl(rb + CT2_RSC_GPR15_REG); | |
915 | ||
916 | if ((nfc_ver >= CT2_NFC_VER_VALID) && | |
917 | (wgn == (__A2T_AHB_LOAD | __WGN_READY))) { | |
918 | ||
919 | bfa_ioc_ct2_wait_till_nfc_running(rb); | |
920 | ||
921 | bfa_ioc_ct2_nfc_clk_reset(rb); | |
922 | } else { | |
923 | bfa_ioc_ct2_nfc_halt(rb); | |
924 | ||
925 | bfa_ioc_ct2_clk_reset(rb); | |
926 | bfa_ioc_ct2_mac_reset(rb); | |
927 | bfa_ioc_ct2_clk_reset(rb); | |
928 | ||
929 | } | |
8b070b4a | 930 | } |
e1aaab89 VMG |
931 | /* |
932 | * The very first PCIe DMA Read done by LPU fails with a fatal error, | |
933 | * when Address Translation Cache (ATC) has been enabled by system BIOS. | |
934 | * | |
935 | * Workaround: | |
936 | * Disable Invalidated Tag Match Enable capability by setting the bit 26 | |
937 | * of CHIP_MISC_PRG to 0, by default it is set to 1. | |
938 | */ | |
939 | r32 = readl(rb + CT2_CHIP_MISC_PRG); | |
940 | writel((r32 & 0xfbffffff), (rb + CT2_CHIP_MISC_PRG)); | |
775c7742 | 941 | |
a6b963db KG |
942 | /* |
943 | * Mask the interrupts and clear any | |
227fab90 | 944 | * pending interrupts left by BIOS/EFI |
a6b963db | 945 | */ |
227fab90 | 946 | |
a6b963db KG |
947 | writel(1, (rb + CT2_LPU0_HOSTFN_MBOX0_MSK)); |
948 | writel(1, (rb + CT2_LPU1_HOSTFN_MBOX0_MSK)); | |
949 | ||
950 | /* For first time initialization, no need to clear interrupts */ | |
951 | r32 = readl(rb + HOST_SEM5_REG); | |
952 | if (r32 & 0x1) { | |
227fab90 | 953 | r32 = readl((rb + CT2_LPU0_HOSTFN_CMD_STAT)); |
a6b963db | 954 | if (r32 == 1) { |
227fab90 | 955 | writel(1, (rb + CT2_LPU0_HOSTFN_CMD_STAT)); |
a6b963db KG |
956 | readl((rb + CT2_LPU0_HOSTFN_CMD_STAT)); |
957 | } | |
227fab90 | 958 | r32 = readl((rb + CT2_LPU1_HOSTFN_CMD_STAT)); |
a6b963db | 959 | if (r32 == 1) { |
227fab90 KG |
960 | writel(1, (rb + CT2_LPU1_HOSTFN_CMD_STAT)); |
961 | readl((rb + CT2_LPU1_HOSTFN_CMD_STAT)); | |
a6b963db KG |
962 | } |
963 | } | |
964 | ||
10a07379 KG |
965 | bfa_ioc_ct2_mem_init(rb); |
966 | ||
227fab90 KG |
967 | writel(BFI_IOC_UNINIT, (rb + CT2_BFA_IOC0_STATE_REG)); |
968 | writel(BFI_IOC_UNINIT, (rb + CT2_BFA_IOC1_STATE_REG)); | |
a6b963db | 969 | |
11189208 KG |
970 | return BFA_STATUS_OK; |
971 | } | |
c679b599 VMG |
972 | |
973 | static void | |
974 | bfa_ioc_ct_set_cur_ioc_fwstate(struct bfa_ioc_s *ioc, | |
975 | enum bfi_ioc_state fwstate) | |
976 | { | |
977 | writel(fwstate, ioc->ioc_regs.ioc_fwstate); | |
978 | } | |
979 | ||
980 | static enum bfi_ioc_state | |
981 | bfa_ioc_ct_get_cur_ioc_fwstate(struct bfa_ioc_s *ioc) | |
982 | { | |
983 | return (enum bfi_ioc_state)readl(ioc->ioc_regs.ioc_fwstate); | |
984 | } | |
985 | ||
986 | static void | |
987 | bfa_ioc_ct_set_alt_ioc_fwstate(struct bfa_ioc_s *ioc, | |
988 | enum bfi_ioc_state fwstate) | |
989 | { | |
990 | writel(fwstate, ioc->ioc_regs.alt_ioc_fwstate); | |
991 | } | |
992 | ||
993 | static enum bfi_ioc_state | |
994 | bfa_ioc_ct_get_alt_ioc_fwstate(struct bfa_ioc_s *ioc) | |
995 | { | |
996 | return (enum bfi_ioc_state) readl(ioc->ioc_regs.alt_ioc_fwstate); | |
997 | } |