blob: de4e726a1263cc1ca563d21aec5536b8c51f4a9c [file] [log] [blame]
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002 * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
Krishna Gudipati0a20de42010-03-05 19:34:20 -08003 * 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
Maggie Zhangf16a1752010-12-09 19:12:32 -080018#include "bfad_drv.h"
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070019#include "bfa_ioc.h"
Krishna Gudipati11189202011-06-13 15:50:35 -070020#include "bfi_reg.h"
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070021#include "bfa_defs.h"
Krishna Gudipati0a20de42010-03-05 19:34:20 -080022
23BFA_TRC_FILE(CNA, IOC_CT);
24
Krishna Gudipatif1d584d2010-12-13 16:17:11 -080025#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
Krishna Gudipati0a20de42010-03-05 19:34:20 -080034/*
35 * forward declarations
36 */
Krishna Gudipati0a20de42010-03-05 19:34:20 -080037static bfa_boolean_t bfa_ioc_ct_firmware_lock(struct bfa_ioc_s *ioc);
38static void bfa_ioc_ct_firmware_unlock(struct bfa_ioc_s *ioc);
Krishna Gudipatif1d584d2010-12-13 16:17:11 -080039static void bfa_ioc_ct_notify_fail(struct bfa_ioc_s *ioc);
Krishna Gudipati0a20de42010-03-05 19:34:20 -080040static void bfa_ioc_ct_ownership_reset(struct bfa_ioc_s *ioc);
Jing Huang45d7f0c2011-04-13 11:45:53 -070041static bfa_boolean_t bfa_ioc_ct_sync_start(struct bfa_ioc_s *ioc);
Krishna Gudipatif1d584d2010-12-13 16:17:11 -080042static void bfa_ioc_ct_sync_join(struct bfa_ioc_s *ioc);
43static void bfa_ioc_ct_sync_leave(struct bfa_ioc_s *ioc);
44static void bfa_ioc_ct_sync_ack(struct bfa_ioc_s *ioc);
45static bfa_boolean_t bfa_ioc_ct_sync_complete(struct bfa_ioc_s *ioc);
Krishna Gudipati0a20de42010-03-05 19:34:20 -080046
Maggie52f94b62010-11-29 18:21:32 -080047static struct bfa_ioc_hwif_s hwif_ct;
Krishna Gudipati11189202011-06-13 15:50:35 -070048static struct bfa_ioc_hwif_s hwif_ct2;
Krishna Gudipati0a20de42010-03-05 19:34:20 -080049
Jing Huang5fbe25c2010-10-18 17:17:23 -070050/*
Krishna Gudipati0a20de42010-03-05 19:34:20 -080051 * Return true if firmware of current driver matches the running firmware.
52 */
53static bfa_boolean_t
54bfa_ioc_ct_firmware_lock(struct bfa_ioc_s *ioc)
55{
56 enum bfi_ioc_state ioc_fwstate;
Krishna Gudipatid1c61f82010-03-05 19:38:44 -080057 u32 usecnt;
Krishna Gudipati0a20de42010-03-05 19:34:20 -080058 struct bfi_ioc_image_hdr_s fwhdr;
59
Krishna Gudipati0a20de42010-03-05 19:34:20 -080060 bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg);
Jing Huang53440262010-10-18 17:12:29 -070061 usecnt = readl(ioc->ioc_regs.ioc_usage_reg);
Krishna Gudipati0a20de42010-03-05 19:34:20 -080062
Jing Huang5fbe25c2010-10-18 17:17:23 -070063 /*
Krishna Gudipati0a20de42010-03-05 19:34:20 -080064 * If usage count is 0, always return TRUE.
65 */
66 if (usecnt == 0) {
Jing Huang53440262010-10-18 17:12:29 -070067 writel(1, ioc->ioc_regs.ioc_usage_reg);
Krishna Gudipati5a0adae2011-06-24 20:22:56 -070068 readl(ioc->ioc_regs.ioc_usage_sem_reg);
Maggie Zhangf7f738122010-12-09 19:08:43 -080069 writel(1, ioc->ioc_regs.ioc_usage_sem_reg);
Krishna Gudipatif1d584d2010-12-13 16:17:11 -080070 writel(0, ioc->ioc_regs.ioc_fail_sync);
Krishna Gudipati0a20de42010-03-05 19:34:20 -080071 bfa_trc(ioc, usecnt);
72 return BFA_TRUE;
73 }
74
Jing Huang53440262010-10-18 17:12:29 -070075 ioc_fwstate = readl(ioc->ioc_regs.ioc_fwstate);
Krishna Gudipati0a20de42010-03-05 19:34:20 -080076 bfa_trc(ioc, ioc_fwstate);
77
Jing Huang5fbe25c2010-10-18 17:17:23 -070078 /*
Krishna Gudipati0a20de42010-03-05 19:34:20 -080079 * Use count cannot be non-zero and chip in uninitialized state.
80 */
Jing Huangd4b671c2010-12-26 21:46:35 -080081 WARN_ON(ioc_fwstate == BFI_IOC_UNINIT);
Krishna Gudipati0a20de42010-03-05 19:34:20 -080082
Jing Huang5fbe25c2010-10-18 17:17:23 -070083 /*
Krishna Gudipati0a20de42010-03-05 19:34:20 -080084 * Check if another driver with a different firmware is active
85 */
86 bfa_ioc_fwver_get(ioc, &fwhdr);
87 if (!bfa_ioc_fwver_cmp(ioc, &fwhdr)) {
Krishna Gudipati5a0adae2011-06-24 20:22:56 -070088 readl(ioc->ioc_regs.ioc_usage_sem_reg);
Maggie Zhangf7f738122010-12-09 19:08:43 -080089 writel(1, ioc->ioc_regs.ioc_usage_sem_reg);
Krishna Gudipati0a20de42010-03-05 19:34:20 -080090 bfa_trc(ioc, usecnt);
91 return BFA_FALSE;
92 }
93
Jing Huang5fbe25c2010-10-18 17:17:23 -070094 /*
Krishna Gudipati0a20de42010-03-05 19:34:20 -080095 * Same firmware version. Increment the reference count.
96 */
97 usecnt++;
Jing Huang53440262010-10-18 17:12:29 -070098 writel(usecnt, ioc->ioc_regs.ioc_usage_reg);
Krishna Gudipati5a0adae2011-06-24 20:22:56 -070099 readl(ioc->ioc_regs.ioc_usage_sem_reg);
Maggie Zhangf7f738122010-12-09 19:08:43 -0800100 writel(1, ioc->ioc_regs.ioc_usage_sem_reg);
Krishna Gudipati0a20de42010-03-05 19:34:20 -0800101 bfa_trc(ioc, usecnt);
102 return BFA_TRUE;
103}
104
105static void
106bfa_ioc_ct_firmware_unlock(struct bfa_ioc_s *ioc)
107{
Krishna Gudipatid1c61f82010-03-05 19:38:44 -0800108 u32 usecnt;
Krishna Gudipati0a20de42010-03-05 19:34:20 -0800109
Jing Huang5fbe25c2010-10-18 17:17:23 -0700110 /*
Krishna Gudipati0a20de42010-03-05 19:34:20 -0800111 * decrement usage count
112 */
113 bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg);
Jing Huang53440262010-10-18 17:12:29 -0700114 usecnt = readl(ioc->ioc_regs.ioc_usage_reg);
Jing Huangd4b671c2010-12-26 21:46:35 -0800115 WARN_ON(usecnt <= 0);
Krishna Gudipati0a20de42010-03-05 19:34:20 -0800116
117 usecnt--;
Jing Huang53440262010-10-18 17:12:29 -0700118 writel(usecnt, ioc->ioc_regs.ioc_usage_reg);
Krishna Gudipati0a20de42010-03-05 19:34:20 -0800119 bfa_trc(ioc, usecnt);
120
Krishna Gudipati5a0adae2011-06-24 20:22:56 -0700121 readl(ioc->ioc_regs.ioc_usage_sem_reg);
Maggie Zhangf7f738122010-12-09 19:08:43 -0800122 writel(1, ioc->ioc_regs.ioc_usage_sem_reg);
Krishna Gudipati0a20de42010-03-05 19:34:20 -0800123}
124
Jing Huang5fbe25c2010-10-18 17:17:23 -0700125/*
Krishna Gudipati0a20de42010-03-05 19:34:20 -0800126 * Notify other functions on HB failure.
127 */
128static void
Krishna Gudipatif1d584d2010-12-13 16:17:11 -0800129bfa_ioc_ct_notify_fail(struct bfa_ioc_s *ioc)
Krishna Gudipati0a20de42010-03-05 19:34:20 -0800130{
Krishna Gudipati11189202011-06-13 15:50:35 -0700131 if (bfa_ioc_is_cna(ioc)) {
Jing Huang53440262010-10-18 17:12:29 -0700132 writel(__FW_INIT_HALT_P, ioc->ioc_regs.ll_halt);
Krishna Gudipatif1d584d2010-12-13 16:17:11 -0800133 writel(__FW_INIT_HALT_P, ioc->ioc_regs.alt_ll_halt);
Krishna Gudipati816e49b2010-03-05 19:36:56 -0800134 /* Wait for halt to take effect */
Jing Huang53440262010-10-18 17:12:29 -0700135 readl(ioc->ioc_regs.ll_halt);
Krishna Gudipatif1d584d2010-12-13 16:17:11 -0800136 readl(ioc->ioc_regs.alt_ll_halt);
Krishna Gudipati816e49b2010-03-05 19:36:56 -0800137 } else {
Krishna Gudipati11189202011-06-13 15:50:35 -0700138 writel(~0U, ioc->ioc_regs.err_set);
Jing Huang53440262010-10-18 17:12:29 -0700139 readl(ioc->ioc_regs.err_set);
Krishna Gudipati816e49b2010-03-05 19:36:56 -0800140 }
Krishna Gudipati0a20de42010-03-05 19:34:20 -0800141}
142
Jing Huang5fbe25c2010-10-18 17:17:23 -0700143/*
Krishna Gudipati0a20de42010-03-05 19:34:20 -0800144 * Host to LPU mailbox message addresses
145 */
Krishna Gudipati11189202011-06-13 15:50:35 -0700146static struct { u32 hfn_mbox, lpu_mbox, hfn_pgn; } ct_fnreg[] = {
Krishna Gudipati0a20de42010-03-05 19:34:20 -0800147 { HOSTFN0_LPU_MBOX0_0, LPU_HOSTFN0_MBOX0_0, HOST_PAGE_NUM_FN0 },
148 { HOSTFN1_LPU_MBOX0_8, LPU_HOSTFN1_MBOX0_8, HOST_PAGE_NUM_FN1 },
149 { HOSTFN2_LPU_MBOX0_0, LPU_HOSTFN2_MBOX0_0, HOST_PAGE_NUM_FN2 },
150 { HOSTFN3_LPU_MBOX0_8, LPU_HOSTFN3_MBOX0_8, HOST_PAGE_NUM_FN3 }
151};
152
Jing Huang5fbe25c2010-10-18 17:17:23 -0700153/*
Krishna Gudipati0a20de42010-03-05 19:34:20 -0800154 * Host <-> LPU mailbox command/status registers - port 0
155 */
Krishna Gudipati11189202011-06-13 15:50:35 -0700156static struct { u32 hfn, lpu; } ct_p0reg[] = {
157 { HOSTFN0_LPU0_CMD_STAT, LPU0_HOSTFN0_CMD_STAT },
158 { HOSTFN1_LPU0_CMD_STAT, LPU0_HOSTFN1_CMD_STAT },
159 { HOSTFN2_LPU0_CMD_STAT, LPU0_HOSTFN2_CMD_STAT },
160 { HOSTFN3_LPU0_CMD_STAT, LPU0_HOSTFN3_CMD_STAT }
Krishna Gudipati0a20de42010-03-05 19:34:20 -0800161};
162
Jing Huang5fbe25c2010-10-18 17:17:23 -0700163/*
Krishna Gudipati0a20de42010-03-05 19:34:20 -0800164 * Host <-> LPU mailbox command/status registers - port 1
165 */
Krishna Gudipati11189202011-06-13 15:50:35 -0700166static struct { u32 hfn, lpu; } ct_p1reg[] = {
167 { HOSTFN0_LPU1_CMD_STAT, LPU1_HOSTFN0_CMD_STAT },
168 { HOSTFN1_LPU1_CMD_STAT, LPU1_HOSTFN1_CMD_STAT },
169 { HOSTFN2_LPU1_CMD_STAT, LPU1_HOSTFN2_CMD_STAT },
170 { HOSTFN3_LPU1_CMD_STAT, LPU1_HOSTFN3_CMD_STAT }
171};
172
Krishna Gudipati8b070b42011-06-13 15:52:40 -0700173static struct { uint32_t hfn_mbox, lpu_mbox, hfn_pgn, hfn, lpu, lpu_read; }
174 ct2_reg[] = {
Krishna Gudipati11189202011-06-13 15:50:35 -0700175 { CT2_HOSTFN_LPU0_MBOX0, CT2_LPU0_HOSTFN_MBOX0, CT2_HOSTFN_PAGE_NUM,
Krishna Gudipati8b070b42011-06-13 15:52:40 -0700176 CT2_HOSTFN_LPU0_CMD_STAT, CT2_LPU0_HOSTFN_CMD_STAT,
177 CT2_HOSTFN_LPU0_READ_STAT},
Krishna Gudipati11189202011-06-13 15:50:35 -0700178 { CT2_HOSTFN_LPU1_MBOX0, CT2_LPU1_HOSTFN_MBOX0, CT2_HOSTFN_PAGE_NUM,
Krishna Gudipati8b070b42011-06-13 15:52:40 -0700179 CT2_HOSTFN_LPU1_CMD_STAT, CT2_LPU1_HOSTFN_CMD_STAT,
180 CT2_HOSTFN_LPU1_READ_STAT},
Krishna Gudipati0a20de42010-03-05 19:34:20 -0800181};
182
183static void
184bfa_ioc_ct_reg_init(struct bfa_ioc_s *ioc)
185{
Jing Huang53440262010-10-18 17:12:29 -0700186 void __iomem *rb;
Krishna Gudipati0a20de42010-03-05 19:34:20 -0800187 int pcifn = bfa_ioc_pcifn(ioc);
188
189 rb = bfa_ioc_bar0(ioc);
190
Krishna Gudipati11189202011-06-13 15:50:35 -0700191 ioc->ioc_regs.hfn_mbox = rb + ct_fnreg[pcifn].hfn_mbox;
192 ioc->ioc_regs.lpu_mbox = rb + ct_fnreg[pcifn].lpu_mbox;
193 ioc->ioc_regs.host_page_num_fn = rb + ct_fnreg[pcifn].hfn_pgn;
Krishna Gudipati0a20de42010-03-05 19:34:20 -0800194
195 if (ioc->port_id == 0) {
196 ioc->ioc_regs.heartbeat = rb + BFA_IOC0_HBEAT_REG;
197 ioc->ioc_regs.ioc_fwstate = rb + BFA_IOC0_STATE_REG;
Krishna Gudipatif1d584d2010-12-13 16:17:11 -0800198 ioc->ioc_regs.alt_ioc_fwstate = rb + BFA_IOC1_STATE_REG;
Krishna Gudipati11189202011-06-13 15:50:35 -0700199 ioc->ioc_regs.hfn_mbox_cmd = rb + ct_p0reg[pcifn].hfn;
200 ioc->ioc_regs.lpu_mbox_cmd = rb + ct_p0reg[pcifn].lpu;
Krishna Gudipati0a20de42010-03-05 19:34:20 -0800201 ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P0;
Krishna Gudipatif1d584d2010-12-13 16:17:11 -0800202 ioc->ioc_regs.alt_ll_halt = rb + FW_INIT_HALT_P1;
Krishna Gudipati0a20de42010-03-05 19:34:20 -0800203 } else {
204 ioc->ioc_regs.heartbeat = (rb + BFA_IOC1_HBEAT_REG);
205 ioc->ioc_regs.ioc_fwstate = (rb + BFA_IOC1_STATE_REG);
Krishna Gudipatif1d584d2010-12-13 16:17:11 -0800206 ioc->ioc_regs.alt_ioc_fwstate = rb + BFA_IOC0_STATE_REG;
Krishna Gudipati11189202011-06-13 15:50:35 -0700207 ioc->ioc_regs.hfn_mbox_cmd = rb + ct_p1reg[pcifn].hfn;
208 ioc->ioc_regs.lpu_mbox_cmd = rb + ct_p1reg[pcifn].lpu;
Krishna Gudipati0a20de42010-03-05 19:34:20 -0800209 ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P1;
Krishna Gudipatif1d584d2010-12-13 16:17:11 -0800210 ioc->ioc_regs.alt_ll_halt = rb + FW_INIT_HALT_P0;
Krishna Gudipati0a20de42010-03-05 19:34:20 -0800211 }
212
213 /*
214 * PSS control registers
215 */
216 ioc->ioc_regs.pss_ctl_reg = (rb + PSS_CTL_REG);
Krishna Gudipati8b651b42010-03-05 19:34:44 -0800217 ioc->ioc_regs.pss_err_status_reg = (rb + PSS_ERR_STATUS_REG);
Krishna Gudipati11189202011-06-13 15:50:35 -0700218 ioc->ioc_regs.app_pll_fast_ctl_reg = (rb + APP_PLL_LCLK_CTL_REG);
219 ioc->ioc_regs.app_pll_slow_ctl_reg = (rb + APP_PLL_SCLK_CTL_REG);
Krishna Gudipati0a20de42010-03-05 19:34:20 -0800220
221 /*
222 * IOC semaphore registers and serialization
223 */
224 ioc->ioc_regs.ioc_sem_reg = (rb + HOST_SEM0_REG);
225 ioc->ioc_regs.ioc_usage_sem_reg = (rb + HOST_SEM1_REG);
226 ioc->ioc_regs.ioc_init_sem_reg = (rb + HOST_SEM2_REG);
227 ioc->ioc_regs.ioc_usage_reg = (rb + BFA_FW_USE_COUNT);
Krishna Gudipatif1d584d2010-12-13 16:17:11 -0800228 ioc->ioc_regs.ioc_fail_sync = (rb + BFA_IOC_FAIL_SYNC);
Krishna Gudipati0a20de42010-03-05 19:34:20 -0800229
Jing Huang5fbe25c2010-10-18 17:17:23 -0700230 /*
Krishna Gudipati0a20de42010-03-05 19:34:20 -0800231 * sram memory access
232 */
233 ioc->ioc_regs.smem_page_start = (rb + PSS_SMEM_PAGE_START);
234 ioc->ioc_regs.smem_pg0 = BFI_IOC_SMEM_PG0_CT;
Krishna Gudipati816e49b2010-03-05 19:36:56 -0800235
236 /*
237 * err set reg : for notification of hb failure in fcmode
238 */
239 ioc->ioc_regs.err_set = (rb + ERR_SET_REG);
Krishna Gudipati0a20de42010-03-05 19:34:20 -0800240}
241
Krishna Gudipati11189202011-06-13 15:50:35 -0700242static void
243bfa_ioc_ct2_reg_init(struct bfa_ioc_s *ioc)
244{
245 void __iomem *rb;
246 int port = bfa_ioc_portid(ioc);
247
248 rb = bfa_ioc_bar0(ioc);
249
250 ioc->ioc_regs.hfn_mbox = rb + ct2_reg[port].hfn_mbox;
251 ioc->ioc_regs.lpu_mbox = rb + ct2_reg[port].lpu_mbox;
252 ioc->ioc_regs.host_page_num_fn = rb + ct2_reg[port].hfn_pgn;
253 ioc->ioc_regs.hfn_mbox_cmd = rb + ct2_reg[port].hfn;
254 ioc->ioc_regs.lpu_mbox_cmd = rb + ct2_reg[port].lpu;
Krishna Gudipati8b070b42011-06-13 15:52:40 -0700255 ioc->ioc_regs.lpu_read_stat = rb + ct2_reg[port].lpu_read;
Krishna Gudipati11189202011-06-13 15:50:35 -0700256
257 if (port == 0) {
258 ioc->ioc_regs.heartbeat = rb + CT2_BFA_IOC0_HBEAT_REG;
259 ioc->ioc_regs.ioc_fwstate = rb + CT2_BFA_IOC0_STATE_REG;
260 ioc->ioc_regs.alt_ioc_fwstate = rb + CT2_BFA_IOC1_STATE_REG;
261 ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P0;
262 ioc->ioc_regs.alt_ll_halt = rb + FW_INIT_HALT_P1;
263 } else {
264 ioc->ioc_regs.heartbeat = (rb + CT2_BFA_IOC1_HBEAT_REG);
265 ioc->ioc_regs.ioc_fwstate = (rb + CT2_BFA_IOC1_STATE_REG);
266 ioc->ioc_regs.alt_ioc_fwstate = rb + CT2_BFA_IOC0_STATE_REG;
267 ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P1;
268 ioc->ioc_regs.alt_ll_halt = rb + FW_INIT_HALT_P0;
269 }
270
271 /*
272 * PSS control registers
273 */
274 ioc->ioc_regs.pss_ctl_reg = (rb + PSS_CTL_REG);
275 ioc->ioc_regs.pss_err_status_reg = (rb + PSS_ERR_STATUS_REG);
276 ioc->ioc_regs.app_pll_fast_ctl_reg = (rb + CT2_APP_PLL_LCLK_CTL_REG);
277 ioc->ioc_regs.app_pll_slow_ctl_reg = (rb + CT2_APP_PLL_SCLK_CTL_REG);
278
279 /*
280 * IOC semaphore registers and serialization
281 */
282 ioc->ioc_regs.ioc_sem_reg = (rb + CT2_HOST_SEM0_REG);
283 ioc->ioc_regs.ioc_usage_sem_reg = (rb + CT2_HOST_SEM1_REG);
284 ioc->ioc_regs.ioc_init_sem_reg = (rb + CT2_HOST_SEM2_REG);
Krishna Gudipati775c7742011-06-13 15:52:12 -0700285 ioc->ioc_regs.ioc_usage_reg = (rb + CT2_BFA_FW_USE_COUNT);
286 ioc->ioc_regs.ioc_fail_sync = (rb + CT2_BFA_IOC_FAIL_SYNC);
Krishna Gudipati11189202011-06-13 15:50:35 -0700287
288 /*
289 * sram memory access
290 */
291 ioc->ioc_regs.smem_page_start = (rb + PSS_SMEM_PAGE_START);
292 ioc->ioc_regs.smem_pg0 = BFI_IOC_SMEM_PG0_CT;
293
294 /*
295 * err set reg : for notification of hb failure in fcmode
296 */
297 ioc->ioc_regs.err_set = (rb + ERR_SET_REG);
298}
299
Jing Huang5fbe25c2010-10-18 17:17:23 -0700300/*
Krishna Gudipati0a20de42010-03-05 19:34:20 -0800301 * Initialize IOC to port mapping.
302 */
303
304#define FNC_PERS_FN_SHIFT(__fn) ((__fn) * 8)
305static void
306bfa_ioc_ct_map_port(struct bfa_ioc_s *ioc)
307{
Jing Huang53440262010-10-18 17:12:29 -0700308 void __iomem *rb = ioc->pcidev.pci_bar_kva;
Krishna Gudipatid1c61f82010-03-05 19:38:44 -0800309 u32 r32;
Krishna Gudipati0a20de42010-03-05 19:34:20 -0800310
Jing Huang5fbe25c2010-10-18 17:17:23 -0700311 /*
Krishna Gudipati0a20de42010-03-05 19:34:20 -0800312 * For catapult, base port id on personality register and IOC type
313 */
Jing Huang53440262010-10-18 17:12:29 -0700314 r32 = readl(rb + FNC_PERS_REG);
Krishna Gudipati0a20de42010-03-05 19:34:20 -0800315 r32 >>= FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc));
316 ioc->port_id = (r32 & __F0_PORT_MAP_MK) >> __F0_PORT_MAP_SH;
317
318 bfa_trc(ioc, bfa_ioc_pcifn(ioc));
319 bfa_trc(ioc, ioc->port_id);
320}
321
Krishna Gudipati11189202011-06-13 15:50:35 -0700322static void
323bfa_ioc_ct2_map_port(struct bfa_ioc_s *ioc)
324{
Krishna Gudipati5a0adae2011-06-24 20:22:56 -0700325 void __iomem *rb = ioc->pcidev.pci_bar_kva;
326 u32 r32;
327
328 r32 = readl(rb + CT2_HOSTFN_PERSONALITY0);
329 ioc->port_id = ((r32 & __FC_LL_PORT_MAP__MK) >> __FC_LL_PORT_MAP__SH);
Krishna Gudipati11189202011-06-13 15:50:35 -0700330
331 bfa_trc(ioc, bfa_ioc_pcifn(ioc));
332 bfa_trc(ioc, ioc->port_id);
333}
334
Jing Huang5fbe25c2010-10-18 17:17:23 -0700335/*
Krishna Gudipati0a20de42010-03-05 19:34:20 -0800336 * Set interrupt mode for a function: INTX or MSIX
337 */
338static void
339bfa_ioc_ct_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix)
340{
Jing Huang53440262010-10-18 17:12:29 -0700341 void __iomem *rb = ioc->pcidev.pci_bar_kva;
Krishna Gudipatid1c61f82010-03-05 19:38:44 -0800342 u32 r32, mode;
Krishna Gudipati0a20de42010-03-05 19:34:20 -0800343
Jing Huang53440262010-10-18 17:12:29 -0700344 r32 = readl(rb + FNC_PERS_REG);
Krishna Gudipati0a20de42010-03-05 19:34:20 -0800345 bfa_trc(ioc, r32);
346
347 mode = (r32 >> FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc))) &
348 __F0_INTX_STATUS;
349
Jing Huang5fbe25c2010-10-18 17:17:23 -0700350 /*
Krishna Gudipati0a20de42010-03-05 19:34:20 -0800351 * If already in desired mode, do not change anything
352 */
Krishna Gudipati11189202011-06-13 15:50:35 -0700353 if ((!msix && mode) || (msix && !mode))
Krishna Gudipati0a20de42010-03-05 19:34:20 -0800354 return;
355
356 if (msix)
357 mode = __F0_INTX_STATUS_MSIX;
358 else
359 mode = __F0_INTX_STATUS_INTA;
360
361 r32 &= ~(__F0_INTX_STATUS << FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc)));
362 r32 |= (mode << FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc)));
363 bfa_trc(ioc, r32);
364
Jing Huang53440262010-10-18 17:12:29 -0700365 writel(r32, rb + FNC_PERS_REG);
Krishna Gudipati0a20de42010-03-05 19:34:20 -0800366}
367
Krishna Gudipati8b070b42011-06-13 15:52:40 -0700368bfa_boolean_t
369bfa_ioc_ct2_lpu_read_stat(struct bfa_ioc_s *ioc)
370{
371 u32 r32;
372
373 r32 = readl(ioc->ioc_regs.lpu_read_stat);
374 if (r32) {
375 writel(1, ioc->ioc_regs.lpu_read_stat);
376 return BFA_TRUE;
377 }
378
379 return BFA_FALSE;
380}
381
Jing Huang5fbe25c2010-10-18 17:17:23 -0700382/*
Krishna Gudipati0a20de42010-03-05 19:34:20 -0800383 * Cleanup hw semaphore and usecnt registers
384 */
385static void
386bfa_ioc_ct_ownership_reset(struct bfa_ioc_s *ioc)
387{
388
Krishna Gudipati7ac83b12012-09-21 17:24:21 -0700389 bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg);
390 writel(0, ioc->ioc_regs.ioc_usage_reg);
391 readl(ioc->ioc_regs.ioc_usage_sem_reg);
392 writel(1, ioc->ioc_regs.ioc_usage_sem_reg);
Krishna Gudipati0a20de42010-03-05 19:34:20 -0800393
Krishna Gudipati7ac83b12012-09-21 17:24:21 -0700394 writel(0, ioc->ioc_regs.ioc_fail_sync);
Krishna Gudipati0a20de42010-03-05 19:34:20 -0800395 /*
396 * Read the hw sem reg to make sure that it is locked
397 * before we clear it. If it is not locked, writing 1
398 * will lock it instead of clearing it.
399 */
Jing Huang53440262010-10-18 17:12:29 -0700400 readl(ioc->ioc_regs.ioc_sem_reg);
Maggie Zhangf7f738122010-12-09 19:08:43 -0800401 writel(1, ioc->ioc_regs.ioc_sem_reg);
Krishna Gudipati0a20de42010-03-05 19:34:20 -0800402}
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700403
Jing Huang45d7f0c2011-04-13 11:45:53 -0700404static bfa_boolean_t
405bfa_ioc_ct_sync_start(struct bfa_ioc_s *ioc)
406{
407 uint32_t r32 = readl(ioc->ioc_regs.ioc_fail_sync);
408 uint32_t sync_reqd = bfa_ioc_ct_get_sync_reqd(r32);
409
410 /*
411 * Driver load time. If the sync required bit for this PCI fn
412 * is set, it is due to an unclean exit by the driver for this
413 * PCI fn in the previous incarnation. Whoever comes here first
414 * should clean it up, no matter which PCI fn.
415 */
416
417 if (sync_reqd & bfa_ioc_ct_sync_pos(ioc)) {
418 writel(0, ioc->ioc_regs.ioc_fail_sync);
419 writel(1, ioc->ioc_regs.ioc_usage_reg);
420 writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate);
421 writel(BFI_IOC_UNINIT, ioc->ioc_regs.alt_ioc_fwstate);
422 return BFA_TRUE;
423 }
424
425 return bfa_ioc_ct_sync_complete(ioc);
426}
427
Jing Huang8f4bfad2010-12-26 21:50:10 -0800428/*
Krishna Gudipatif1d584d2010-12-13 16:17:11 -0800429 * Synchronized IOC failure processing routines
430 */
431static void
432bfa_ioc_ct_sync_join(struct bfa_ioc_s *ioc)
433{
434 uint32_t r32 = readl(ioc->ioc_regs.ioc_fail_sync);
435 uint32_t sync_pos = bfa_ioc_ct_sync_reqd_pos(ioc);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700436
Krishna Gudipatif1d584d2010-12-13 16:17:11 -0800437 writel((r32 | sync_pos), ioc->ioc_regs.ioc_fail_sync);
438}
439
440static void
441bfa_ioc_ct_sync_leave(struct bfa_ioc_s *ioc)
442{
443 uint32_t r32 = readl(ioc->ioc_regs.ioc_fail_sync);
444 uint32_t sync_msk = bfa_ioc_ct_sync_reqd_pos(ioc) |
445 bfa_ioc_ct_sync_pos(ioc);
446
447 writel((r32 & ~sync_msk), ioc->ioc_regs.ioc_fail_sync);
448}
449
450static void
451bfa_ioc_ct_sync_ack(struct bfa_ioc_s *ioc)
452{
453 uint32_t r32 = readl(ioc->ioc_regs.ioc_fail_sync);
454
455 writel((r32 | bfa_ioc_ct_sync_pos(ioc)),
456 ioc->ioc_regs.ioc_fail_sync);
457}
458
459static bfa_boolean_t
460bfa_ioc_ct_sync_complete(struct bfa_ioc_s *ioc)
461{
462 uint32_t r32 = readl(ioc->ioc_regs.ioc_fail_sync);
463 uint32_t sync_reqd = bfa_ioc_ct_get_sync_reqd(r32);
464 uint32_t sync_ackd = bfa_ioc_ct_get_sync_ackd(r32);
465 uint32_t tmp_ackd;
466
467 if (sync_ackd == 0)
468 return BFA_TRUE;
469
Jing Huang8f4bfad2010-12-26 21:50:10 -0800470 /*
Krishna Gudipatif1d584d2010-12-13 16:17:11 -0800471 * The check below is to see whether any other PCI fn
472 * has reinitialized the ASIC (reset sync_ackd bits)
473 * and failed again while this IOC was waiting for hw
474 * semaphore (in bfa_iocpf_sm_semwait()).
475 */
476 tmp_ackd = sync_ackd;
477 if ((sync_reqd & bfa_ioc_ct_sync_pos(ioc)) &&
478 !(sync_ackd & bfa_ioc_ct_sync_pos(ioc)))
479 sync_ackd |= bfa_ioc_ct_sync_pos(ioc);
480
481 if (sync_reqd == sync_ackd) {
482 writel(bfa_ioc_ct_clear_sync_ackd(r32),
483 ioc->ioc_regs.ioc_fail_sync);
484 writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
485 writel(BFI_IOC_FAIL, ioc->ioc_regs.alt_ioc_fwstate);
486 return BFA_TRUE;
487 }
488
Jing Huang8f4bfad2010-12-26 21:50:10 -0800489 /*
Krishna Gudipatif1d584d2010-12-13 16:17:11 -0800490 * If another PCI fn reinitialized and failed again while
491 * this IOC was waiting for hw sem, the sync_ackd bit for
492 * this IOC need to be set again to allow reinitialization.
493 */
494 if (tmp_ackd != sync_ackd)
495 writel((r32 | sync_ackd), ioc->ioc_regs.ioc_fail_sync);
496
497 return BFA_FALSE;
498}
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700499
Krishna Gudipati11189202011-06-13 15:50:35 -0700500/**
501 * Called from bfa_ioc_attach() to map asic specific calls.
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700502 */
Krishna Gudipati11189202011-06-13 15:50:35 -0700503static void
504bfa_ioc_set_ctx_hwif(struct bfa_ioc_s *ioc, struct bfa_ioc_hwif_s *hwif)
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700505{
Krishna Gudipati11189202011-06-13 15:50:35 -0700506 hwif->ioc_firmware_lock = bfa_ioc_ct_firmware_lock;
507 hwif->ioc_firmware_unlock = bfa_ioc_ct_firmware_unlock;
508 hwif->ioc_notify_fail = bfa_ioc_ct_notify_fail;
509 hwif->ioc_ownership_reset = bfa_ioc_ct_ownership_reset;
510 hwif->ioc_sync_start = bfa_ioc_ct_sync_start;
511 hwif->ioc_sync_join = bfa_ioc_ct_sync_join;
512 hwif->ioc_sync_leave = bfa_ioc_ct_sync_leave;
513 hwif->ioc_sync_ack = bfa_ioc_ct_sync_ack;
514 hwif->ioc_sync_complete = bfa_ioc_ct_sync_complete;
515}
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700516
Krishna Gudipati11189202011-06-13 15:50:35 -0700517/**
518 * Called from bfa_ioc_attach() to map asic specific calls.
519 */
520void
521bfa_ioc_set_ct_hwif(struct bfa_ioc_s *ioc)
522{
523 bfa_ioc_set_ctx_hwif(ioc, &hwif_ct);
524
525 hwif_ct.ioc_pll_init = bfa_ioc_ct_pll_init;
526 hwif_ct.ioc_reg_init = bfa_ioc_ct_reg_init;
527 hwif_ct.ioc_map_port = bfa_ioc_ct_map_port;
528 hwif_ct.ioc_isr_mode_set = bfa_ioc_ct_isr_mode_set;
529 ioc->ioc_hwif = &hwif_ct;
530}
531
532/**
533 * Called from bfa_ioc_attach() to map asic specific calls.
534 */
535void
536bfa_ioc_set_ct2_hwif(struct bfa_ioc_s *ioc)
537{
538 bfa_ioc_set_ctx_hwif(ioc, &hwif_ct2);
539
540 hwif_ct2.ioc_pll_init = bfa_ioc_ct2_pll_init;
541 hwif_ct2.ioc_reg_init = bfa_ioc_ct2_reg_init;
542 hwif_ct2.ioc_map_port = bfa_ioc_ct2_map_port;
Krishna Gudipati8b070b42011-06-13 15:52:40 -0700543 hwif_ct2.ioc_lpu_read_stat = bfa_ioc_ct2_lpu_read_stat;
Krishna Gudipati11189202011-06-13 15:50:35 -0700544 hwif_ct2.ioc_isr_mode_set = NULL;
545 ioc->ioc_hwif = &hwif_ct2;
546}
547
548/*
Krishna Gudipati3fd45982011-06-24 20:24:08 -0700549 * Workaround for MSI-X resource allocation for catapult-2 with no asic block
Krishna Gudipati11189202011-06-13 15:50:35 -0700550 */
Krishna Gudipati3fd45982011-06-24 20:24:08 -0700551#define HOSTFN_MSIX_DEFAULT 64
Krishna Gudipati10a07372011-06-24 20:23:38 -0700552#define HOSTFN_MSIX_VT_INDEX_MBOX_ERR 0x30138
Krishna Gudipati11189202011-06-13 15:50:35 -0700553#define HOSTFN_MSIX_VT_OFST_NUMVT 0x3013c
554#define __MSIX_VT_NUMVT__MK 0x003ff800
555#define __MSIX_VT_NUMVT__SH 11
556#define __MSIX_VT_NUMVT_(_v) ((_v) << __MSIX_VT_NUMVT__SH)
Krishna Gudipati10a07372011-06-24 20:23:38 -0700557#define __MSIX_VT_OFST_ 0x000007ff
Krishna Gudipati11189202011-06-13 15:50:35 -0700558void
559bfa_ioc_ct2_poweron(struct bfa_ioc_s *ioc)
560{
561 void __iomem *rb = ioc->pcidev.pci_bar_kva;
562 u32 r32;
563
564 r32 = readl(rb + HOSTFN_MSIX_VT_OFST_NUMVT);
Krishna Gudipati10a07372011-06-24 20:23:38 -0700565 if (r32 & __MSIX_VT_NUMVT__MK) {
566 writel(r32 & __MSIX_VT_OFST_,
567 rb + HOSTFN_MSIX_VT_INDEX_MBOX_ERR);
Krishna Gudipati11189202011-06-13 15:50:35 -0700568 return;
Krishna Gudipati10a07372011-06-24 20:23:38 -0700569 }
Krishna Gudipati11189202011-06-13 15:50:35 -0700570
571 writel(__MSIX_VT_NUMVT_(HOSTFN_MSIX_DEFAULT - 1) |
572 HOSTFN_MSIX_DEFAULT * bfa_ioc_pcifn(ioc),
573 rb + HOSTFN_MSIX_VT_OFST_NUMVT);
Krishna Gudipati10a07372011-06-24 20:23:38 -0700574 writel(HOSTFN_MSIX_DEFAULT * bfa_ioc_pcifn(ioc),
575 rb + HOSTFN_MSIX_VT_INDEX_MBOX_ERR);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700576}
577
578bfa_status_t
Krishna Gudipati11189202011-06-13 15:50:35 -0700579bfa_ioc_ct_pll_init(void __iomem *rb, enum bfi_asic_mode mode)
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700580{
581 u32 pll_sclk, pll_fclk, r32;
Krishna Gudipati11189202011-06-13 15:50:35 -0700582 bfa_boolean_t fcmode = (mode == BFI_ASIC_MODE_FC);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700583
Krishna Gudipati11189202011-06-13 15:50:35 -0700584 pll_sclk = __APP_PLL_SCLK_LRESETN | __APP_PLL_SCLK_ENARST |
585 __APP_PLL_SCLK_RSEL200500 | __APP_PLL_SCLK_P0_1(3U) |
586 __APP_PLL_SCLK_JITLMT0_1(3U) |
587 __APP_PLL_SCLK_CNTLMT0_1(1U);
588 pll_fclk = __APP_PLL_LCLK_LRESETN | __APP_PLL_LCLK_ENARST |
589 __APP_PLL_LCLK_RSEL200500 | __APP_PLL_LCLK_P0_1(3U) |
590 __APP_PLL_LCLK_JITLMT0_1(3U) |
591 __APP_PLL_LCLK_CNTLMT0_1(1U);
592
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700593 if (fcmode) {
Jing Huang53440262010-10-18 17:12:29 -0700594 writel(0, (rb + OP_MODE));
595 writel(__APP_EMS_CMLCKSEL | __APP_EMS_REFCKBUFEN2 |
596 __APP_EMS_CHANNEL_SEL, (rb + ETH_MAC_SER_REG));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700597 } else {
Jing Huang53440262010-10-18 17:12:29 -0700598 writel(__GLOBAL_FCOE_MODE, (rb + OP_MODE));
599 writel(__APP_EMS_REFCKBUFEN1, (rb + ETH_MAC_SER_REG));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700600 }
Jing Huang53440262010-10-18 17:12:29 -0700601 writel(BFI_IOC_UNINIT, (rb + BFA_IOC0_STATE_REG));
602 writel(BFI_IOC_UNINIT, (rb + BFA_IOC1_STATE_REG));
603 writel(0xffffffffU, (rb + HOSTFN0_INT_MSK));
604 writel(0xffffffffU, (rb + HOSTFN1_INT_MSK));
605 writel(0xffffffffU, (rb + HOSTFN0_INT_STATUS));
606 writel(0xffffffffU, (rb + HOSTFN1_INT_STATUS));
607 writel(0xffffffffU, (rb + HOSTFN0_INT_MSK));
608 writel(0xffffffffU, (rb + HOSTFN1_INT_MSK));
Krishna Gudipati11189202011-06-13 15:50:35 -0700609 writel(pll_sclk | __APP_PLL_SCLK_LOGIC_SOFT_RESET,
610 rb + APP_PLL_SCLK_CTL_REG);
611 writel(pll_fclk | __APP_PLL_LCLK_LOGIC_SOFT_RESET,
612 rb + APP_PLL_LCLK_CTL_REG);
613 writel(pll_sclk | __APP_PLL_SCLK_LOGIC_SOFT_RESET |
614 __APP_PLL_SCLK_ENABLE, rb + APP_PLL_SCLK_CTL_REG);
615 writel(pll_fclk | __APP_PLL_LCLK_LOGIC_SOFT_RESET |
616 __APP_PLL_LCLK_ENABLE, rb + APP_PLL_LCLK_CTL_REG);
Jing Huang53440262010-10-18 17:12:29 -0700617 readl(rb + HOSTFN0_INT_MSK);
Jing Huang6a18b162010-10-18 17:08:54 -0700618 udelay(2000);
Jing Huang53440262010-10-18 17:12:29 -0700619 writel(0xffffffffU, (rb + HOSTFN0_INT_STATUS));
620 writel(0xffffffffU, (rb + HOSTFN1_INT_STATUS));
Krishna Gudipati11189202011-06-13 15:50:35 -0700621 writel(pll_sclk | __APP_PLL_SCLK_ENABLE, rb + APP_PLL_SCLK_CTL_REG);
622 writel(pll_fclk | __APP_PLL_LCLK_ENABLE, rb + APP_PLL_LCLK_CTL_REG);
623
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700624 if (!fcmode) {
Jing Huang53440262010-10-18 17:12:29 -0700625 writel(__PMM_1T_RESET_P, (rb + PMM_1T_RESET_REG_P0));
626 writel(__PMM_1T_RESET_P, (rb + PMM_1T_RESET_REG_P1));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700627 }
Jing Huang53440262010-10-18 17:12:29 -0700628 r32 = readl((rb + PSS_CTL_REG));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700629 r32 &= ~__PSS_LMEM_RESET;
Jing Huang53440262010-10-18 17:12:29 -0700630 writel(r32, (rb + PSS_CTL_REG));
Jing Huang6a18b162010-10-18 17:08:54 -0700631 udelay(1000);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700632 if (!fcmode) {
Jing Huang53440262010-10-18 17:12:29 -0700633 writel(0, (rb + PMM_1T_RESET_REG_P0));
634 writel(0, (rb + PMM_1T_RESET_REG_P1));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700635 }
636
Jing Huang53440262010-10-18 17:12:29 -0700637 writel(__EDRAM_BISTR_START, (rb + MBIST_CTL_REG));
Jing Huang6a18b162010-10-18 17:08:54 -0700638 udelay(1000);
Jing Huang53440262010-10-18 17:12:29 -0700639 r32 = readl((rb + MBIST_STAT_REG));
640 writel(0, (rb + MBIST_CTL_REG));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700641 return BFA_STATUS_OK;
642}
Krishna Gudipati11189202011-06-13 15:50:35 -0700643
Krishna Gudipati11189202011-06-13 15:50:35 -0700644static void
Krishna Gudipati10a07372011-06-24 20:23:38 -0700645bfa_ioc_ct2_sclk_init(void __iomem *rb)
Krishna Gudipati11189202011-06-13 15:50:35 -0700646{
647 u32 r32;
648
649 /*
650 * put s_clk PLL and PLL FSM in reset
651 */
652 r32 = readl((rb + CT2_APP_PLL_SCLK_CTL_REG));
653 r32 &= ~(__APP_PLL_SCLK_ENABLE | __APP_PLL_SCLK_LRESETN);
654 r32 |= (__APP_PLL_SCLK_ENARST | __APP_PLL_SCLK_BYPASS |
655 __APP_PLL_SCLK_LOGIC_SOFT_RESET);
656 writel(r32, (rb + CT2_APP_PLL_SCLK_CTL_REG));
657
658 /*
Krishna Gudipati10a07372011-06-24 20:23:38 -0700659 * Ignore mode and program for the max clock (which is FC16)
660 * Firmware/NFC will do the PLL init appropiately
Krishna Gudipati11189202011-06-13 15:50:35 -0700661 */
662 r32 = readl((rb + CT2_APP_PLL_SCLK_CTL_REG));
663 r32 &= ~(__APP_PLL_SCLK_REFCLK_SEL | __APP_PLL_SCLK_CLK_DIV2);
Krishna Gudipati10a07372011-06-24 20:23:38 -0700664 writel(r32, (rb + CT2_APP_PLL_SCLK_CTL_REG));
Krishna Gudipati11189202011-06-13 15:50:35 -0700665
666 /*
Krishna Gudipati775c7742011-06-13 15:52:12 -0700667 * while doing PLL init dont clock gate ethernet subsystem
Krishna Gudipati11189202011-06-13 15:50:35 -0700668 */
Krishna Gudipati775c7742011-06-13 15:52:12 -0700669 r32 = readl((rb + CT2_CHIP_MISC_PRG));
670 writel(r32 | __ETH_CLK_ENABLE_PORT0, (rb + CT2_CHIP_MISC_PRG));
Krishna Gudipati11189202011-06-13 15:50:35 -0700671
Krishna Gudipati775c7742011-06-13 15:52:12 -0700672 r32 = readl((rb + CT2_PCIE_MISC_REG));
673 writel(r32 | __ETH_CLK_ENABLE_PORT1, (rb + CT2_PCIE_MISC_REG));
Krishna Gudipati11189202011-06-13 15:50:35 -0700674
675 /*
676 * set sclk value
677 */
678 r32 = readl((rb + CT2_APP_PLL_SCLK_CTL_REG));
679 r32 &= (__P_SCLK_PLL_LOCK | __APP_PLL_SCLK_REFCLK_SEL |
680 __APP_PLL_SCLK_CLK_DIV2);
681 writel(r32 | 0x1061731b, (rb + CT2_APP_PLL_SCLK_CTL_REG));
682
683 /*
684 * poll for s_clk lock or delay 1ms
685 */
686 udelay(1000);
Krishna Gudipati11189202011-06-13 15:50:35 -0700687}
688
689static void
Krishna Gudipati10a07372011-06-24 20:23:38 -0700690bfa_ioc_ct2_lclk_init(void __iomem *rb)
Krishna Gudipati11189202011-06-13 15:50:35 -0700691{
692 u32 r32;
693
694 /*
695 * put l_clk PLL and PLL FSM in reset
696 */
697 r32 = readl((rb + CT2_APP_PLL_LCLK_CTL_REG));
698 r32 &= ~(__APP_PLL_LCLK_ENABLE | __APP_PLL_LCLK_LRESETN);
699 r32 |= (__APP_PLL_LCLK_ENARST | __APP_PLL_LCLK_BYPASS |
700 __APP_PLL_LCLK_LOGIC_SOFT_RESET);
701 writel(r32, (rb + CT2_APP_PLL_LCLK_CTL_REG));
702
703 /*
Krishna Gudipati10a07372011-06-24 20:23:38 -0700704 * set LPU speed (set for FC16 which will work for other modes)
Krishna Gudipati11189202011-06-13 15:50:35 -0700705 */
706 r32 = readl((rb + CT2_CHIP_MISC_PRG));
Krishna Gudipati10a07372011-06-24 20:23:38 -0700707 writel(r32, (rb + CT2_CHIP_MISC_PRG));
Krishna Gudipati11189202011-06-13 15:50:35 -0700708
709 /*
Krishna Gudipati10a07372011-06-24 20:23:38 -0700710 * set LPU half speed (set for FC16 which will work for other modes)
Krishna Gudipati11189202011-06-13 15:50:35 -0700711 */
712 r32 = readl((rb + CT2_APP_PLL_LCLK_CTL_REG));
Krishna Gudipati10a07372011-06-24 20:23:38 -0700713 writel(r32, (rb + CT2_APP_PLL_LCLK_CTL_REG));
Krishna Gudipati11189202011-06-13 15:50:35 -0700714
715 /*
Krishna Gudipati10a07372011-06-24 20:23:38 -0700716 * set lclk for mode (set for FC16)
Krishna Gudipati11189202011-06-13 15:50:35 -0700717 */
718 r32 = readl((rb + CT2_APP_PLL_LCLK_CTL_REG));
719 r32 &= (__P_LCLK_PLL_LOCK | __APP_LPUCLK_HALFSPEED);
Krishna Gudipati10a07372011-06-24 20:23:38 -0700720 r32 |= 0x20c1731b;
Krishna Gudipati11189202011-06-13 15:50:35 -0700721 writel(r32, (rb + CT2_APP_PLL_LCLK_CTL_REG));
722
723 /*
724 * poll for s_clk lock or delay 1ms
725 */
726 udelay(1000);
Krishna Gudipati10a07372011-06-24 20:23:38 -0700727}
728
729static void
730bfa_ioc_ct2_mem_init(void __iomem *rb)
731{
732 u32 r32;
733
734 r32 = readl((rb + PSS_CTL_REG));
735 r32 &= ~__PSS_LMEM_RESET;
736 writel(r32, (rb + PSS_CTL_REG));
737 udelay(1000);
738
739 writel(__EDRAM_BISTR_START, (rb + CT2_MBIST_CTL_REG));
740 udelay(1000);
741 writel(0, (rb + CT2_MBIST_CTL_REG));
742}
743
744void
745bfa_ioc_ct2_mac_reset(void __iomem *rb)
746{
Krishna Gudipati10a07372011-06-24 20:23:38 -0700747 /* put port0, port1 MAC & AHB in reset */
748 writel((__CSI_MAC_RESET | __CSI_MAC_AHB_RESET),
749 rb + CT2_CSI_MAC_CONTROL_REG(0));
750 writel((__CSI_MAC_RESET | __CSI_MAC_AHB_RESET),
751 rb + CT2_CSI_MAC_CONTROL_REG(1));
Krishna Gudipati11189202011-06-13 15:50:35 -0700752}
753
Krishna Gudipati227fab92012-09-21 17:24:52 -0700754static void
755bfa_ioc_ct2_enable_flash(void __iomem *rb)
756{
757 u32 r32;
758
759 r32 = readl((rb + PSS_GPIO_OUT_REG));
760 writel(r32 & ~1, (rb + PSS_GPIO_OUT_REG));
761 r32 = readl((rb + PSS_GPIO_OE_REG));
762 writel(r32 | 1, (rb + PSS_GPIO_OE_REG));
763}
764
Krishna Gudipati10a07372011-06-24 20:23:38 -0700765#define CT2_NFC_MAX_DELAY 1000
Krishna Gudipati227fab92012-09-21 17:24:52 -0700766#define CT2_NFC_PAUSE_MAX_DELAY 4000
767#define CT2_NFC_VER_VALID 0x147
768#define CT2_NFC_STATE_RUNNING 0x20000001
Krishna Gudipatia6b963d2012-03-13 17:39:22 -0700769#define BFA_IOC_PLL_POLL 1000000
770
771static bfa_boolean_t
772bfa_ioc_ct2_nfc_halted(void __iomem *rb)
773{
774 u32 r32;
775
776 r32 = readl(rb + CT2_NFC_CSR_SET_REG);
777 if (r32 & __NFC_CONTROLLER_HALTED)
778 return BFA_TRUE;
779
780 return BFA_FALSE;
781}
782
783static void
Krishna Gudipati227fab92012-09-21 17:24:52 -0700784bfa_ioc_ct2_nfc_halt(void __iomem *rb)
785{
786 int i;
787
788 writel(__HALT_NFC_CONTROLLER, rb + CT2_NFC_CSR_SET_REG);
789 for (i = 0; i < CT2_NFC_MAX_DELAY; i++) {
790 if (bfa_ioc_ct2_nfc_halted(rb))
791 break;
792 udelay(1000);
793 }
794 WARN_ON(!bfa_ioc_ct2_nfc_halted(rb));
795}
796
797static void
Krishna Gudipatia6b963d2012-03-13 17:39:22 -0700798bfa_ioc_ct2_nfc_resume(void __iomem *rb)
799{
800 u32 r32;
801 int i;
802
803 writel(__HALT_NFC_CONTROLLER, rb + CT2_NFC_CSR_CLR_REG);
804 for (i = 0; i < CT2_NFC_MAX_DELAY; i++) {
805 r32 = readl(rb + CT2_NFC_CSR_SET_REG);
806 if (!(r32 & __NFC_CONTROLLER_HALTED))
807 return;
808 udelay(1000);
809 }
810 WARN_ON(1);
811}
812
Krishna Gudipati227fab92012-09-21 17:24:52 -0700813static void
814bfa_ioc_ct2_clk_reset(void __iomem *rb)
815{
816 u32 r32;
817
818 bfa_ioc_ct2_sclk_init(rb);
819 bfa_ioc_ct2_lclk_init(rb);
820
821 /*
822 * release soft reset on s_clk & l_clk
823 */
824 r32 = readl((rb + CT2_APP_PLL_SCLK_CTL_REG));
825 writel(r32 & ~__APP_PLL_SCLK_LOGIC_SOFT_RESET,
826 (rb + CT2_APP_PLL_SCLK_CTL_REG));
827
828 r32 = readl((rb + CT2_APP_PLL_LCLK_CTL_REG));
829 writel(r32 & ~__APP_PLL_LCLK_LOGIC_SOFT_RESET,
830 (rb + CT2_APP_PLL_LCLK_CTL_REG));
831
832}
833
834static void
835bfa_ioc_ct2_nfc_clk_reset(void __iomem *rb)
836{
837 u32 r32, i;
838
839 r32 = readl((rb + PSS_CTL_REG));
840 r32 |= (__PSS_LPU0_RESET | __PSS_LPU1_RESET);
841 writel(r32, (rb + PSS_CTL_REG));
842
843 writel(__RESET_AND_START_SCLK_LCLK_PLLS, rb + CT2_CSI_FW_CTL_SET_REG);
844
845 for (i = 0; i < BFA_IOC_PLL_POLL; i++) {
846 r32 = readl(rb + CT2_NFC_FLASH_STS_REG);
847
848 if ((r32 & __FLASH_PLL_INIT_AND_RESET_IN_PROGRESS))
849 break;
850 }
851 WARN_ON(!(r32 & __FLASH_PLL_INIT_AND_RESET_IN_PROGRESS));
852
853 for (i = 0; i < BFA_IOC_PLL_POLL; i++) {
854 r32 = readl(rb + CT2_NFC_FLASH_STS_REG);
855
856 if (!(r32 & __FLASH_PLL_INIT_AND_RESET_IN_PROGRESS))
857 break;
858 }
859 WARN_ON((r32 & __FLASH_PLL_INIT_AND_RESET_IN_PROGRESS));
860
861 r32 = readl(rb + CT2_CSI_FW_CTL_REG);
862 WARN_ON((r32 & __RESET_AND_START_SCLK_LCLK_PLLS));
863}
864
865static void
866bfa_ioc_ct2_wait_till_nfc_running(void __iomem *rb)
867{
868 u32 r32;
869 int i;
870
871 if (bfa_ioc_ct2_nfc_halted(rb))
872 bfa_ioc_ct2_nfc_resume(rb);
873 for (i = 0; i < CT2_NFC_PAUSE_MAX_DELAY; i++) {
874 r32 = readl(rb + CT2_NFC_STS_REG);
875 if (r32 == CT2_NFC_STATE_RUNNING)
876 return;
877 udelay(1000);
878 }
879
880 r32 = readl(rb + CT2_NFC_STS_REG);
881 WARN_ON(!(r32 == CT2_NFC_STATE_RUNNING));
882}
883
Krishna Gudipati11189202011-06-13 15:50:35 -0700884bfa_status_t
885bfa_ioc_ct2_pll_init(void __iomem *rb, enum bfi_asic_mode mode)
886{
Krishna Gudipati227fab92012-09-21 17:24:52 -0700887 u32 wgn, r32, nfc_ver;
Krishna Gudipati8b070b42011-06-13 15:52:40 -0700888
Krishna Gudipati10a07372011-06-24 20:23:38 -0700889 wgn = readl(rb + CT2_WGN_STATUS);
Krishna Gudipatia6b963d2012-03-13 17:39:22 -0700890
Krishna Gudipati227fab92012-09-21 17:24:52 -0700891 if (wgn == (__WGN_READY | __GLBL_PF_VF_CFG_RDY)) {
892 /*
893 * If flash is corrupted, enable flash explicitly
894 */
895 bfa_ioc_ct2_clk_reset(rb);
896 bfa_ioc_ct2_enable_flash(rb);
Krishna Gudipatia6b963d2012-03-13 17:39:22 -0700897
898 bfa_ioc_ct2_mac_reset(rb);
Krishna Gudipatia6b963d2012-03-13 17:39:22 -0700899
Krishna Gudipati227fab92012-09-21 17:24:52 -0700900 bfa_ioc_ct2_clk_reset(rb);
901 bfa_ioc_ct2_enable_flash(rb);
Krishna Gudipatia6b963d2012-03-13 17:39:22 -0700902
Krishna Gudipati227fab92012-09-21 17:24:52 -0700903 } else {
904 nfc_ver = readl(rb + CT2_RSC_GPR15_REG);
Krishna Gudipatia6b963d2012-03-13 17:39:22 -0700905
Krishna Gudipati227fab92012-09-21 17:24:52 -0700906 if ((nfc_ver >= CT2_NFC_VER_VALID) &&
907 (wgn == (__A2T_AHB_LOAD | __WGN_READY))) {
908
909 bfa_ioc_ct2_wait_till_nfc_running(rb);
910
911 bfa_ioc_ct2_nfc_clk_reset(rb);
912 } else {
913 bfa_ioc_ct2_nfc_halt(rb);
914
915 bfa_ioc_ct2_clk_reset(rb);
916 bfa_ioc_ct2_mac_reset(rb);
917 bfa_ioc_ct2_clk_reset(rb);
918
919 }
Krishna Gudipati10a07372011-06-24 20:23:38 -0700920 }
Krishna Gudipati8b070b42011-06-13 15:52:40 -0700921
Krishna Gudipati10a07372011-06-24 20:23:38 -0700922 /*
923 * Mask the interrupts and clear any
Krishna Gudipati227fab92012-09-21 17:24:52 -0700924 * pending interrupts left by BIOS/EFI
Krishna Gudipati10a07372011-06-24 20:23:38 -0700925 */
Krishna Gudipati227fab92012-09-21 17:24:52 -0700926
Krishna Gudipati10a07372011-06-24 20:23:38 -0700927 writel(1, (rb + CT2_LPU0_HOSTFN_MBOX0_MSK));
928 writel(1, (rb + CT2_LPU1_HOSTFN_MBOX0_MSK));
Krishna Gudipati8b070b42011-06-13 15:52:40 -0700929
Krishna Gudipatia6b963d2012-03-13 17:39:22 -0700930 /* For first time initialization, no need to clear interrupts */
931 r32 = readl(rb + HOST_SEM5_REG);
932 if (r32 & 0x1) {
Krishna Gudipati227fab92012-09-21 17:24:52 -0700933 r32 = readl((rb + CT2_LPU0_HOSTFN_CMD_STAT));
Krishna Gudipatia6b963d2012-03-13 17:39:22 -0700934 if (r32 == 1) {
Krishna Gudipati227fab92012-09-21 17:24:52 -0700935 writel(1, (rb + CT2_LPU0_HOSTFN_CMD_STAT));
Krishna Gudipatia6b963d2012-03-13 17:39:22 -0700936 readl((rb + CT2_LPU0_HOSTFN_CMD_STAT));
937 }
Krishna Gudipati227fab92012-09-21 17:24:52 -0700938 r32 = readl((rb + CT2_LPU1_HOSTFN_CMD_STAT));
Krishna Gudipatia6b963d2012-03-13 17:39:22 -0700939 if (r32 == 1) {
Krishna Gudipati227fab92012-09-21 17:24:52 -0700940 writel(1, (rb + CT2_LPU1_HOSTFN_CMD_STAT));
941 readl((rb + CT2_LPU1_HOSTFN_CMD_STAT));
Krishna Gudipatia6b963d2012-03-13 17:39:22 -0700942 }
Krishna Gudipati8b070b42011-06-13 15:52:40 -0700943 }
Krishna Gudipati775c7742011-06-13 15:52:12 -0700944
Krishna Gudipati10a07372011-06-24 20:23:38 -0700945 bfa_ioc_ct2_mem_init(rb);
946
Krishna Gudipati227fab92012-09-21 17:24:52 -0700947 writel(BFI_IOC_UNINIT, (rb + CT2_BFA_IOC0_STATE_REG));
948 writel(BFI_IOC_UNINIT, (rb + CT2_BFA_IOC1_STATE_REG));
Krishna Gudipatia6b963d2012-03-13 17:39:22 -0700949
Krishna Gudipati11189202011-06-13 15:50:35 -0700950 return BFA_STATUS_OK;
951}