bfa_ioc_ct.c 11 KB

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