bfa_ioc_cb.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. /*
  2. * Copyright (c) 2005-2014 Brocade Communications Systems, Inc.
  3. * Copyright (c) 2014- QLogic Corporation.
  4. * All rights reserved
  5. * www.qlogic.com
  6. *
  7. * Linux driver for QLogic BR-series Fibre Channel Host Bus Adapter.
  8. *
  9. * This program is free software; you can redistribute it and/or modify it
  10. * under the terms of the GNU General Public License (GPL) Version 2 as
  11. * published by the Free Software Foundation
  12. *
  13. * This program is distributed in the hope that it will be useful, but
  14. * WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * General Public License for more details.
  17. */
  18. #include "bfad_drv.h"
  19. #include "bfa_ioc.h"
  20. #include "bfi_reg.h"
  21. #include "bfa_defs.h"
  22. BFA_TRC_FILE(CNA, IOC_CB);
  23. #define bfa_ioc_cb_join_pos(__ioc) ((u32) (1 << BFA_IOC_CB_JOIN_SH))
  24. /*
  25. * forward declarations
  26. */
  27. static bfa_boolean_t bfa_ioc_cb_firmware_lock(struct bfa_ioc_s *ioc);
  28. static void bfa_ioc_cb_firmware_unlock(struct bfa_ioc_s *ioc);
  29. static void bfa_ioc_cb_reg_init(struct bfa_ioc_s *ioc);
  30. static void bfa_ioc_cb_map_port(struct bfa_ioc_s *ioc);
  31. static void bfa_ioc_cb_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix);
  32. static void bfa_ioc_cb_notify_fail(struct bfa_ioc_s *ioc);
  33. static void bfa_ioc_cb_ownership_reset(struct bfa_ioc_s *ioc);
  34. static bfa_boolean_t bfa_ioc_cb_sync_start(struct bfa_ioc_s *ioc);
  35. static void bfa_ioc_cb_sync_join(struct bfa_ioc_s *ioc);
  36. static void bfa_ioc_cb_sync_leave(struct bfa_ioc_s *ioc);
  37. static void bfa_ioc_cb_sync_ack(struct bfa_ioc_s *ioc);
  38. static bfa_boolean_t bfa_ioc_cb_sync_complete(struct bfa_ioc_s *ioc);
  39. static void bfa_ioc_cb_set_cur_ioc_fwstate(
  40. struct bfa_ioc_s *ioc, enum bfi_ioc_state fwstate);
  41. static enum bfi_ioc_state bfa_ioc_cb_get_cur_ioc_fwstate(struct bfa_ioc_s *ioc);
  42. static void bfa_ioc_cb_set_alt_ioc_fwstate(
  43. struct bfa_ioc_s *ioc, enum bfi_ioc_state fwstate);
  44. static enum bfi_ioc_state bfa_ioc_cb_get_alt_ioc_fwstate(struct bfa_ioc_s *ioc);
  45. static struct bfa_ioc_hwif_s hwif_cb;
  46. /*
  47. * Called from bfa_ioc_attach() to map asic specific calls.
  48. */
  49. void
  50. bfa_ioc_set_cb_hwif(struct bfa_ioc_s *ioc)
  51. {
  52. hwif_cb.ioc_pll_init = bfa_ioc_cb_pll_init;
  53. hwif_cb.ioc_firmware_lock = bfa_ioc_cb_firmware_lock;
  54. hwif_cb.ioc_firmware_unlock = bfa_ioc_cb_firmware_unlock;
  55. hwif_cb.ioc_reg_init = bfa_ioc_cb_reg_init;
  56. hwif_cb.ioc_map_port = bfa_ioc_cb_map_port;
  57. hwif_cb.ioc_isr_mode_set = bfa_ioc_cb_isr_mode_set;
  58. hwif_cb.ioc_notify_fail = bfa_ioc_cb_notify_fail;
  59. hwif_cb.ioc_ownership_reset = bfa_ioc_cb_ownership_reset;
  60. hwif_cb.ioc_sync_start = bfa_ioc_cb_sync_start;
  61. hwif_cb.ioc_sync_join = bfa_ioc_cb_sync_join;
  62. hwif_cb.ioc_sync_leave = bfa_ioc_cb_sync_leave;
  63. hwif_cb.ioc_sync_ack = bfa_ioc_cb_sync_ack;
  64. hwif_cb.ioc_sync_complete = bfa_ioc_cb_sync_complete;
  65. hwif_cb.ioc_set_fwstate = bfa_ioc_cb_set_cur_ioc_fwstate;
  66. hwif_cb.ioc_get_fwstate = bfa_ioc_cb_get_cur_ioc_fwstate;
  67. hwif_cb.ioc_set_alt_fwstate = bfa_ioc_cb_set_alt_ioc_fwstate;
  68. hwif_cb.ioc_get_alt_fwstate = bfa_ioc_cb_get_alt_ioc_fwstate;
  69. ioc->ioc_hwif = &hwif_cb;
  70. }
  71. /*
  72. * Return true if firmware of current driver matches the running firmware.
  73. */
  74. static bfa_boolean_t
  75. bfa_ioc_cb_firmware_lock(struct bfa_ioc_s *ioc)
  76. {
  77. enum bfi_ioc_state alt_fwstate, cur_fwstate;
  78. struct bfi_ioc_image_hdr_s fwhdr;
  79. cur_fwstate = bfa_ioc_cb_get_cur_ioc_fwstate(ioc);
  80. bfa_trc(ioc, cur_fwstate);
  81. alt_fwstate = bfa_ioc_cb_get_alt_ioc_fwstate(ioc);
  82. bfa_trc(ioc, alt_fwstate);
  83. /*
  84. * Uninit implies this is the only driver as of now.
  85. */
  86. if (cur_fwstate == BFI_IOC_UNINIT)
  87. return BFA_TRUE;
  88. /*
  89. * Check if another driver with a different firmware is active
  90. */
  91. bfa_ioc_fwver_get(ioc, &fwhdr);
  92. if (!bfa_ioc_fwver_cmp(ioc, &fwhdr) &&
  93. alt_fwstate != BFI_IOC_DISABLED) {
  94. bfa_trc(ioc, alt_fwstate);
  95. return BFA_FALSE;
  96. }
  97. return BFA_TRUE;
  98. }
  99. static void
  100. bfa_ioc_cb_firmware_unlock(struct bfa_ioc_s *ioc)
  101. {
  102. }
  103. /*
  104. * Notify other functions on HB failure.
  105. */
  106. static void
  107. bfa_ioc_cb_notify_fail(struct bfa_ioc_s *ioc)
  108. {
  109. writel(~0U, ioc->ioc_regs.err_set);
  110. readl(ioc->ioc_regs.err_set);
  111. }
  112. /*
  113. * Host to LPU mailbox message addresses
  114. */
  115. static struct { u32 hfn_mbox, lpu_mbox, hfn_pgn; } iocreg_fnreg[] = {
  116. { HOSTFN0_LPU_MBOX0_0, LPU_HOSTFN0_MBOX0_0, HOST_PAGE_NUM_FN0 },
  117. { HOSTFN1_LPU_MBOX0_8, LPU_HOSTFN1_MBOX0_8, HOST_PAGE_NUM_FN1 }
  118. };
  119. /*
  120. * Host <-> LPU mailbox command/status registers
  121. */
  122. static struct { u32 hfn, lpu; } iocreg_mbcmd[] = {
  123. { HOSTFN0_LPU0_CMD_STAT, LPU0_HOSTFN0_CMD_STAT },
  124. { HOSTFN1_LPU1_CMD_STAT, LPU1_HOSTFN1_CMD_STAT }
  125. };
  126. static void
  127. bfa_ioc_cb_reg_init(struct bfa_ioc_s *ioc)
  128. {
  129. void __iomem *rb;
  130. int pcifn = bfa_ioc_pcifn(ioc);
  131. rb = bfa_ioc_bar0(ioc);
  132. ioc->ioc_regs.hfn_mbox = rb + iocreg_fnreg[pcifn].hfn_mbox;
  133. ioc->ioc_regs.lpu_mbox = rb + iocreg_fnreg[pcifn].lpu_mbox;
  134. ioc->ioc_regs.host_page_num_fn = rb + iocreg_fnreg[pcifn].hfn_pgn;
  135. if (ioc->port_id == 0) {
  136. ioc->ioc_regs.heartbeat = rb + BFA_IOC0_HBEAT_REG;
  137. ioc->ioc_regs.ioc_fwstate = rb + BFA_IOC0_STATE_REG;
  138. ioc->ioc_regs.alt_ioc_fwstate = rb + BFA_IOC1_STATE_REG;
  139. } else {
  140. ioc->ioc_regs.heartbeat = (rb + BFA_IOC1_HBEAT_REG);
  141. ioc->ioc_regs.ioc_fwstate = (rb + BFA_IOC1_STATE_REG);
  142. ioc->ioc_regs.alt_ioc_fwstate = (rb + BFA_IOC0_STATE_REG);
  143. }
  144. /*
  145. * Host <-> LPU mailbox command/status registers
  146. */
  147. ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd[pcifn].hfn;
  148. ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd[pcifn].lpu;
  149. /*
  150. * PSS control registers
  151. */
  152. ioc->ioc_regs.pss_ctl_reg = (rb + PSS_CTL_REG);
  153. ioc->ioc_regs.pss_err_status_reg = (rb + PSS_ERR_STATUS_REG);
  154. ioc->ioc_regs.app_pll_fast_ctl_reg = (rb + APP_PLL_LCLK_CTL_REG);
  155. ioc->ioc_regs.app_pll_slow_ctl_reg = (rb + APP_PLL_SCLK_CTL_REG);
  156. /*
  157. * IOC semaphore registers and serialization
  158. */
  159. ioc->ioc_regs.ioc_sem_reg = (rb + HOST_SEM0_REG);
  160. ioc->ioc_regs.ioc_init_sem_reg = (rb + HOST_SEM2_REG);
  161. /*
  162. * sram memory access
  163. */
  164. ioc->ioc_regs.smem_page_start = (rb + PSS_SMEM_PAGE_START);
  165. ioc->ioc_regs.smem_pg0 = BFI_IOC_SMEM_PG0_CB;
  166. /*
  167. * err set reg : for notification of hb failure
  168. */
  169. ioc->ioc_regs.err_set = (rb + ERR_SET_REG);
  170. }
  171. /*
  172. * Initialize IOC to port mapping.
  173. */
  174. static void
  175. bfa_ioc_cb_map_port(struct bfa_ioc_s *ioc)
  176. {
  177. /*
  178. * For crossbow, port id is same as pci function.
  179. */
  180. ioc->port_id = bfa_ioc_pcifn(ioc);
  181. bfa_trc(ioc, ioc->port_id);
  182. }
  183. /*
  184. * Set interrupt mode for a function: INTX or MSIX
  185. */
  186. static void
  187. bfa_ioc_cb_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix)
  188. {
  189. }
  190. /*
  191. * Synchronized IOC failure processing routines
  192. */
  193. static bfa_boolean_t
  194. bfa_ioc_cb_sync_start(struct bfa_ioc_s *ioc)
  195. {
  196. u32 ioc_fwstate = readl(ioc->ioc_regs.ioc_fwstate);
  197. /**
  198. * Driver load time. If the join bit is set,
  199. * it is due to an unclean exit by the driver for this
  200. * PCI fn in the previous incarnation. Whoever comes here first
  201. * should clean it up, no matter which PCI fn.
  202. */
  203. if (ioc_fwstate & BFA_IOC_CB_JOIN_MASK) {
  204. writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate);
  205. writel(BFI_IOC_UNINIT, ioc->ioc_regs.alt_ioc_fwstate);
  206. return BFA_TRUE;
  207. }
  208. return bfa_ioc_cb_sync_complete(ioc);
  209. }
  210. /*
  211. * Cleanup hw semaphore and usecnt registers
  212. */
  213. static void
  214. bfa_ioc_cb_ownership_reset(struct bfa_ioc_s *ioc)
  215. {
  216. /*
  217. * Read the hw sem reg to make sure that it is locked
  218. * before we clear it. If it is not locked, writing 1
  219. * will lock it instead of clearing it.
  220. */
  221. readl(ioc->ioc_regs.ioc_sem_reg);
  222. writel(1, ioc->ioc_regs.ioc_sem_reg);
  223. }
  224. /*
  225. * Synchronized IOC failure processing routines
  226. */
  227. static void
  228. bfa_ioc_cb_sync_join(struct bfa_ioc_s *ioc)
  229. {
  230. u32 r32 = readl(ioc->ioc_regs.ioc_fwstate);
  231. u32 join_pos = bfa_ioc_cb_join_pos(ioc);
  232. writel((r32 | join_pos), ioc->ioc_regs.ioc_fwstate);
  233. }
  234. static void
  235. bfa_ioc_cb_sync_leave(struct bfa_ioc_s *ioc)
  236. {
  237. u32 r32 = readl(ioc->ioc_regs.ioc_fwstate);
  238. u32 join_pos = bfa_ioc_cb_join_pos(ioc);
  239. writel((r32 & ~join_pos), ioc->ioc_regs.ioc_fwstate);
  240. }
  241. static void
  242. bfa_ioc_cb_set_cur_ioc_fwstate(struct bfa_ioc_s *ioc,
  243. enum bfi_ioc_state fwstate)
  244. {
  245. u32 r32 = readl(ioc->ioc_regs.ioc_fwstate);
  246. writel((fwstate | (r32 & BFA_IOC_CB_JOIN_MASK)),
  247. ioc->ioc_regs.ioc_fwstate);
  248. }
  249. static enum bfi_ioc_state
  250. bfa_ioc_cb_get_cur_ioc_fwstate(struct bfa_ioc_s *ioc)
  251. {
  252. return (enum bfi_ioc_state)(readl(ioc->ioc_regs.ioc_fwstate) &
  253. BFA_IOC_CB_FWSTATE_MASK);
  254. }
  255. static void
  256. bfa_ioc_cb_set_alt_ioc_fwstate(struct bfa_ioc_s *ioc,
  257. enum bfi_ioc_state fwstate)
  258. {
  259. u32 r32 = readl(ioc->ioc_regs.alt_ioc_fwstate);
  260. writel((fwstate | (r32 & BFA_IOC_CB_JOIN_MASK)),
  261. ioc->ioc_regs.alt_ioc_fwstate);
  262. }
  263. static enum bfi_ioc_state
  264. bfa_ioc_cb_get_alt_ioc_fwstate(struct bfa_ioc_s *ioc)
  265. {
  266. return (enum bfi_ioc_state)(readl(ioc->ioc_regs.alt_ioc_fwstate) &
  267. BFA_IOC_CB_FWSTATE_MASK);
  268. }
  269. static void
  270. bfa_ioc_cb_sync_ack(struct bfa_ioc_s *ioc)
  271. {
  272. bfa_ioc_cb_set_cur_ioc_fwstate(ioc, BFI_IOC_FAIL);
  273. }
  274. static bfa_boolean_t
  275. bfa_ioc_cb_sync_complete(struct bfa_ioc_s *ioc)
  276. {
  277. u32 fwstate, alt_fwstate;
  278. fwstate = bfa_ioc_cb_get_cur_ioc_fwstate(ioc);
  279. /*
  280. * At this point, this IOC is hoding the hw sem in the
  281. * start path (fwcheck) OR in the disable/enable path
  282. * OR to check if the other IOC has acknowledged failure.
  283. *
  284. * So, this IOC can be in UNINIT, INITING, DISABLED, FAIL
  285. * or in MEMTEST states. In a normal scenario, this IOC
  286. * can not be in OP state when this function is called.
  287. *
  288. * However, this IOC could still be in OP state when
  289. * the OS driver is starting up, if the OptROM code has
  290. * left it in that state.
  291. *
  292. * If we had marked this IOC's fwstate as BFI_IOC_FAIL
  293. * in the failure case and now, if the fwstate is not
  294. * BFI_IOC_FAIL it implies that the other PCI fn have
  295. * reinitialized the ASIC or this IOC got disabled, so
  296. * return TRUE.
  297. */
  298. if (fwstate == BFI_IOC_UNINIT ||
  299. fwstate == BFI_IOC_INITING ||
  300. fwstate == BFI_IOC_DISABLED ||
  301. fwstate == BFI_IOC_MEMTEST ||
  302. fwstate == BFI_IOC_OP)
  303. return BFA_TRUE;
  304. else {
  305. alt_fwstate = bfa_ioc_cb_get_alt_ioc_fwstate(ioc);
  306. if (alt_fwstate == BFI_IOC_FAIL ||
  307. alt_fwstate == BFI_IOC_DISABLED ||
  308. alt_fwstate == BFI_IOC_UNINIT ||
  309. alt_fwstate == BFI_IOC_INITING ||
  310. alt_fwstate == BFI_IOC_MEMTEST)
  311. return BFA_TRUE;
  312. else
  313. return BFA_FALSE;
  314. }
  315. }
  316. bfa_status_t
  317. bfa_ioc_cb_pll_init(void __iomem *rb, enum bfi_asic_mode fcmode)
  318. {
  319. u32 pll_sclk, pll_fclk, join_bits;
  320. pll_sclk = __APP_PLL_SCLK_ENABLE | __APP_PLL_SCLK_LRESETN |
  321. __APP_PLL_SCLK_P0_1(3U) |
  322. __APP_PLL_SCLK_JITLMT0_1(3U) |
  323. __APP_PLL_SCLK_CNTLMT0_1(3U);
  324. pll_fclk = __APP_PLL_LCLK_ENABLE | __APP_PLL_LCLK_LRESETN |
  325. __APP_PLL_LCLK_RSEL200500 | __APP_PLL_LCLK_P0_1(3U) |
  326. __APP_PLL_LCLK_JITLMT0_1(3U) |
  327. __APP_PLL_LCLK_CNTLMT0_1(3U);
  328. join_bits = readl(rb + BFA_IOC0_STATE_REG) &
  329. BFA_IOC_CB_JOIN_MASK;
  330. writel((BFI_IOC_UNINIT | join_bits), (rb + BFA_IOC0_STATE_REG));
  331. join_bits = readl(rb + BFA_IOC1_STATE_REG) &
  332. BFA_IOC_CB_JOIN_MASK;
  333. writel((BFI_IOC_UNINIT | join_bits), (rb + BFA_IOC1_STATE_REG));
  334. writel(0xffffffffU, (rb + HOSTFN0_INT_MSK));
  335. writel(0xffffffffU, (rb + HOSTFN1_INT_MSK));
  336. writel(0xffffffffU, (rb + HOSTFN0_INT_STATUS));
  337. writel(0xffffffffU, (rb + HOSTFN1_INT_STATUS));
  338. writel(0xffffffffU, (rb + HOSTFN0_INT_MSK));
  339. writel(0xffffffffU, (rb + HOSTFN1_INT_MSK));
  340. writel(__APP_PLL_SCLK_LOGIC_SOFT_RESET, rb + APP_PLL_SCLK_CTL_REG);
  341. writel(__APP_PLL_SCLK_BYPASS | __APP_PLL_SCLK_LOGIC_SOFT_RESET,
  342. rb + APP_PLL_SCLK_CTL_REG);
  343. writel(__APP_PLL_LCLK_LOGIC_SOFT_RESET, rb + APP_PLL_LCLK_CTL_REG);
  344. writel(__APP_PLL_LCLK_BYPASS | __APP_PLL_LCLK_LOGIC_SOFT_RESET,
  345. rb + APP_PLL_LCLK_CTL_REG);
  346. udelay(2);
  347. writel(__APP_PLL_SCLK_LOGIC_SOFT_RESET, rb + APP_PLL_SCLK_CTL_REG);
  348. writel(__APP_PLL_LCLK_LOGIC_SOFT_RESET, rb + APP_PLL_LCLK_CTL_REG);
  349. writel(pll_sclk | __APP_PLL_SCLK_LOGIC_SOFT_RESET,
  350. rb + APP_PLL_SCLK_CTL_REG);
  351. writel(pll_fclk | __APP_PLL_LCLK_LOGIC_SOFT_RESET,
  352. rb + APP_PLL_LCLK_CTL_REG);
  353. udelay(2000);
  354. writel(0xffffffffU, (rb + HOSTFN0_INT_STATUS));
  355. writel(0xffffffffU, (rb + HOSTFN1_INT_STATUS));
  356. writel(pll_sclk, (rb + APP_PLL_SCLK_CTL_REG));
  357. writel(pll_fclk, (rb + APP_PLL_LCLK_CTL_REG));
  358. return BFA_STATUS_OK;
  359. }