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