bfa_ioc_ct.c 11 KB

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