/drivers/scsi/bfa/bfa_ioc_ct.c

https://bitbucket.org/wisechild/galaxy-nexus · C · 526 lines · 337 code · 69 blank · 120 comment · 32 complexity · 29aaa2f13322ca40f92ef934043074da MD5 · raw file

  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. #define bfa_ioc_ct_sync_pos(__ioc) \
  23. ((uint32_t) (1 << bfa_ioc_pcifn(__ioc)))
  24. #define BFA_IOC_SYNC_REQD_SH 16
  25. #define bfa_ioc_ct_get_sync_ackd(__val) (__val & 0x0000ffff)
  26. #define bfa_ioc_ct_clear_sync_ackd(__val) (__val & 0xffff0000)
  27. #define bfa_ioc_ct_get_sync_reqd(__val) (__val >> BFA_IOC_SYNC_REQD_SH)
  28. #define bfa_ioc_ct_sync_reqd_pos(__ioc) \
  29. (bfa_ioc_ct_sync_pos(__ioc) << BFA_IOC_SYNC_REQD_SH)
  30. /*
  31. * forward declarations
  32. */
  33. static bfa_boolean_t bfa_ioc_ct_firmware_lock(struct bfa_ioc_s *ioc);
  34. static void bfa_ioc_ct_firmware_unlock(struct bfa_ioc_s *ioc);
  35. static void bfa_ioc_ct_reg_init(struct bfa_ioc_s *ioc);
  36. static void bfa_ioc_ct_map_port(struct bfa_ioc_s *ioc);
  37. static void bfa_ioc_ct_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix);
  38. static void bfa_ioc_ct_notify_fail(struct bfa_ioc_s *ioc);
  39. static void bfa_ioc_ct_ownership_reset(struct bfa_ioc_s *ioc);
  40. static bfa_boolean_t bfa_ioc_ct_sync_start(struct bfa_ioc_s *ioc);
  41. static void bfa_ioc_ct_sync_join(struct bfa_ioc_s *ioc);
  42. static void bfa_ioc_ct_sync_leave(struct bfa_ioc_s *ioc);
  43. static void bfa_ioc_ct_sync_ack(struct bfa_ioc_s *ioc);
  44. static bfa_boolean_t bfa_ioc_ct_sync_complete(struct bfa_ioc_s *ioc);
  45. static struct bfa_ioc_hwif_s hwif_ct;
  46. /*
  47. * Called from bfa_ioc_attach() to map asic specific calls.
  48. */
  49. void
  50. bfa_ioc_set_ct_hwif(struct bfa_ioc_s *ioc)
  51. {
  52. hwif_ct.ioc_pll_init = bfa_ioc_ct_pll_init;
  53. hwif_ct.ioc_firmware_lock = bfa_ioc_ct_firmware_lock;
  54. hwif_ct.ioc_firmware_unlock = bfa_ioc_ct_firmware_unlock;
  55. hwif_ct.ioc_reg_init = bfa_ioc_ct_reg_init;
  56. hwif_ct.ioc_map_port = bfa_ioc_ct_map_port;
  57. hwif_ct.ioc_isr_mode_set = bfa_ioc_ct_isr_mode_set;
  58. hwif_ct.ioc_notify_fail = bfa_ioc_ct_notify_fail;
  59. hwif_ct.ioc_ownership_reset = bfa_ioc_ct_ownership_reset;
  60. hwif_ct.ioc_sync_start = bfa_ioc_ct_sync_start;
  61. hwif_ct.ioc_sync_join = bfa_ioc_ct_sync_join;
  62. hwif_ct.ioc_sync_leave = bfa_ioc_ct_sync_leave;
  63. hwif_ct.ioc_sync_ack = bfa_ioc_ct_sync_ack;
  64. hwif_ct.ioc_sync_complete = bfa_ioc_ct_sync_complete;
  65. ioc->ioc_hwif = &hwif_ct;
  66. }
  67. /*
  68. * Return true if firmware of current driver matches the running firmware.
  69. */
  70. static bfa_boolean_t
  71. bfa_ioc_ct_firmware_lock(struct bfa_ioc_s *ioc)
  72. {
  73. enum bfi_ioc_state ioc_fwstate;
  74. u32 usecnt;
  75. struct bfi_ioc_image_hdr_s fwhdr;
  76. /*
  77. * Firmware match check is relevant only for CNA.
  78. */
  79. if (!ioc->cna)
  80. return BFA_TRUE;
  81. /*
  82. * If bios boot (flash based) -- do not increment usage count
  83. */
  84. if (bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)) <
  85. BFA_IOC_FWIMG_MINSZ)
  86. return BFA_TRUE;
  87. bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg);
  88. usecnt = readl(ioc->ioc_regs.ioc_usage_reg);
  89. /*
  90. * If usage count is 0, always return TRUE.
  91. */
  92. if (usecnt == 0) {
  93. writel(1, ioc->ioc_regs.ioc_usage_reg);
  94. writel(1, ioc->ioc_regs.ioc_usage_sem_reg);
  95. writel(0, ioc->ioc_regs.ioc_fail_sync);
  96. bfa_trc(ioc, usecnt);
  97. return BFA_TRUE;
  98. }
  99. ioc_fwstate = readl(ioc->ioc_regs.ioc_fwstate);
  100. bfa_trc(ioc, ioc_fwstate);
  101. /*
  102. * Use count cannot be non-zero and chip in uninitialized state.
  103. */
  104. WARN_ON(ioc_fwstate == BFI_IOC_UNINIT);
  105. /*
  106. * Check if another driver with a different firmware is active
  107. */
  108. bfa_ioc_fwver_get(ioc, &fwhdr);
  109. if (!bfa_ioc_fwver_cmp(ioc, &fwhdr)) {
  110. writel(1, ioc->ioc_regs.ioc_usage_sem_reg);
  111. bfa_trc(ioc, usecnt);
  112. return BFA_FALSE;
  113. }
  114. /*
  115. * Same firmware version. Increment the reference count.
  116. */
  117. usecnt++;
  118. writel(usecnt, ioc->ioc_regs.ioc_usage_reg);
  119. writel(1, ioc->ioc_regs.ioc_usage_sem_reg);
  120. bfa_trc(ioc, usecnt);
  121. return BFA_TRUE;
  122. }
  123. static void
  124. bfa_ioc_ct_firmware_unlock(struct bfa_ioc_s *ioc)
  125. {
  126. u32 usecnt;
  127. /*
  128. * Firmware lock is relevant only for CNA.
  129. */
  130. if (!ioc->cna)
  131. return;
  132. /*
  133. * If bios boot (flash based) -- do not decrement usage count
  134. */
  135. if (bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)) <
  136. BFA_IOC_FWIMG_MINSZ)
  137. return;
  138. /*
  139. * decrement usage count
  140. */
  141. bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg);
  142. usecnt = readl(ioc->ioc_regs.ioc_usage_reg);
  143. WARN_ON(usecnt <= 0);
  144. usecnt--;
  145. writel(usecnt, ioc->ioc_regs.ioc_usage_reg);
  146. bfa_trc(ioc, usecnt);
  147. writel(1, ioc->ioc_regs.ioc_usage_sem_reg);
  148. }
  149. /*
  150. * Notify other functions on HB failure.
  151. */
  152. static void
  153. bfa_ioc_ct_notify_fail(struct bfa_ioc_s *ioc)
  154. {
  155. if (ioc->cna) {
  156. writel(__FW_INIT_HALT_P, ioc->ioc_regs.ll_halt);
  157. writel(__FW_INIT_HALT_P, ioc->ioc_regs.alt_ll_halt);
  158. /* Wait for halt to take effect */
  159. readl(ioc->ioc_regs.ll_halt);
  160. readl(ioc->ioc_regs.alt_ll_halt);
  161. } else {
  162. writel(__PSS_ERR_STATUS_SET, ioc->ioc_regs.err_set);
  163. readl(ioc->ioc_regs.err_set);
  164. }
  165. }
  166. /*
  167. * Host to LPU mailbox message addresses
  168. */
  169. static struct { u32 hfn_mbox, lpu_mbox, hfn_pgn; } iocreg_fnreg[] = {
  170. { HOSTFN0_LPU_MBOX0_0, LPU_HOSTFN0_MBOX0_0, HOST_PAGE_NUM_FN0 },
  171. { HOSTFN1_LPU_MBOX0_8, LPU_HOSTFN1_MBOX0_8, HOST_PAGE_NUM_FN1 },
  172. { HOSTFN2_LPU_MBOX0_0, LPU_HOSTFN2_MBOX0_0, HOST_PAGE_NUM_FN2 },
  173. { HOSTFN3_LPU_MBOX0_8, LPU_HOSTFN3_MBOX0_8, HOST_PAGE_NUM_FN3 }
  174. };
  175. /*
  176. * Host <-> LPU mailbox command/status registers - port 0
  177. */
  178. static struct { u32 hfn, lpu; } iocreg_mbcmd_p0[] = {
  179. { HOSTFN0_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN0_MBOX0_CMD_STAT },
  180. { HOSTFN1_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN1_MBOX0_CMD_STAT },
  181. { HOSTFN2_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN2_MBOX0_CMD_STAT },
  182. { HOSTFN3_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN3_MBOX0_CMD_STAT }
  183. };
  184. /*
  185. * Host <-> LPU mailbox command/status registers - port 1
  186. */
  187. static struct { u32 hfn, lpu; } iocreg_mbcmd_p1[] = {
  188. { HOSTFN0_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN0_MBOX0_CMD_STAT },
  189. { HOSTFN1_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN1_MBOX0_CMD_STAT },
  190. { HOSTFN2_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN2_MBOX0_CMD_STAT },
  191. { HOSTFN3_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN3_MBOX0_CMD_STAT }
  192. };
  193. static void
  194. bfa_ioc_ct_reg_init(struct bfa_ioc_s *ioc)
  195. {
  196. void __iomem *rb;
  197. int pcifn = bfa_ioc_pcifn(ioc);
  198. rb = bfa_ioc_bar0(ioc);
  199. ioc->ioc_regs.hfn_mbox = rb + iocreg_fnreg[pcifn].hfn_mbox;
  200. ioc->ioc_regs.lpu_mbox = rb + iocreg_fnreg[pcifn].lpu_mbox;
  201. ioc->ioc_regs.host_page_num_fn = rb + iocreg_fnreg[pcifn].hfn_pgn;
  202. if (ioc->port_id == 0) {
  203. ioc->ioc_regs.heartbeat = rb + BFA_IOC0_HBEAT_REG;
  204. ioc->ioc_regs.ioc_fwstate = rb + BFA_IOC0_STATE_REG;
  205. ioc->ioc_regs.alt_ioc_fwstate = rb + BFA_IOC1_STATE_REG;
  206. ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd_p0[pcifn].hfn;
  207. ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd_p0[pcifn].lpu;
  208. ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P0;
  209. ioc->ioc_regs.alt_ll_halt = rb + FW_INIT_HALT_P1;
  210. } else {
  211. ioc->ioc_regs.heartbeat = (rb + BFA_IOC1_HBEAT_REG);
  212. ioc->ioc_regs.ioc_fwstate = (rb + BFA_IOC1_STATE_REG);
  213. ioc->ioc_regs.alt_ioc_fwstate = rb + BFA_IOC0_STATE_REG;
  214. ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd_p1[pcifn].hfn;
  215. ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd_p1[pcifn].lpu;
  216. ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P1;
  217. ioc->ioc_regs.alt_ll_halt = rb + FW_INIT_HALT_P0;
  218. }
  219. /*
  220. * PSS control registers
  221. */
  222. ioc->ioc_regs.pss_ctl_reg = (rb + PSS_CTL_REG);
  223. ioc->ioc_regs.pss_err_status_reg = (rb + PSS_ERR_STATUS_REG);
  224. ioc->ioc_regs.app_pll_fast_ctl_reg = (rb + APP_PLL_425_CTL_REG);
  225. ioc->ioc_regs.app_pll_slow_ctl_reg = (rb + APP_PLL_312_CTL_REG);
  226. /*
  227. * IOC semaphore registers and serialization
  228. */
  229. ioc->ioc_regs.ioc_sem_reg = (rb + HOST_SEM0_REG);
  230. ioc->ioc_regs.ioc_usage_sem_reg = (rb + HOST_SEM1_REG);
  231. ioc->ioc_regs.ioc_init_sem_reg = (rb + HOST_SEM2_REG);
  232. ioc->ioc_regs.ioc_usage_reg = (rb + BFA_FW_USE_COUNT);
  233. ioc->ioc_regs.ioc_fail_sync = (rb + BFA_IOC_FAIL_SYNC);
  234. /*
  235. * sram memory access
  236. */
  237. ioc->ioc_regs.smem_page_start = (rb + PSS_SMEM_PAGE_START);
  238. ioc->ioc_regs.smem_pg0 = BFI_IOC_SMEM_PG0_CT;
  239. /*
  240. * err set reg : for notification of hb failure in fcmode
  241. */
  242. ioc->ioc_regs.err_set = (rb + ERR_SET_REG);
  243. }
  244. /*
  245. * Initialize IOC to port mapping.
  246. */
  247. #define FNC_PERS_FN_SHIFT(__fn) ((__fn) * 8)
  248. static void
  249. bfa_ioc_ct_map_port(struct bfa_ioc_s *ioc)
  250. {
  251. void __iomem *rb = ioc->pcidev.pci_bar_kva;
  252. u32 r32;
  253. /*
  254. * For catapult, base port id on personality register and IOC type
  255. */
  256. r32 = readl(rb + FNC_PERS_REG);
  257. r32 >>= FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc));
  258. ioc->port_id = (r32 & __F0_PORT_MAP_MK) >> __F0_PORT_MAP_SH;
  259. bfa_trc(ioc, bfa_ioc_pcifn(ioc));
  260. bfa_trc(ioc, ioc->port_id);
  261. }
  262. /*
  263. * Set interrupt mode for a function: INTX or MSIX
  264. */
  265. static void
  266. bfa_ioc_ct_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix)
  267. {
  268. void __iomem *rb = ioc->pcidev.pci_bar_kva;
  269. u32 r32, mode;
  270. r32 = readl(rb + FNC_PERS_REG);
  271. bfa_trc(ioc, r32);
  272. mode = (r32 >> FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc))) &
  273. __F0_INTX_STATUS;
  274. /*
  275. * If already in desired mode, do not change anything
  276. */
  277. if (!msix && mode)
  278. return;
  279. if (msix)
  280. mode = __F0_INTX_STATUS_MSIX;
  281. else
  282. mode = __F0_INTX_STATUS_INTA;
  283. r32 &= ~(__F0_INTX_STATUS << FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc)));
  284. r32 |= (mode << FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc)));
  285. bfa_trc(ioc, r32);
  286. writel(r32, rb + FNC_PERS_REG);
  287. }
  288. /*
  289. * Cleanup hw semaphore and usecnt registers
  290. */
  291. static void
  292. bfa_ioc_ct_ownership_reset(struct bfa_ioc_s *ioc)
  293. {
  294. if (ioc->cna) {
  295. bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg);
  296. writel(0, ioc->ioc_regs.ioc_usage_reg);
  297. writel(1, ioc->ioc_regs.ioc_usage_sem_reg);
  298. }
  299. /*
  300. * Read the hw sem reg to make sure that it is locked
  301. * before we clear it. If it is not locked, writing 1
  302. * will lock it instead of clearing it.
  303. */
  304. readl(ioc->ioc_regs.ioc_sem_reg);
  305. writel(1, ioc->ioc_regs.ioc_sem_reg);
  306. }
  307. static bfa_boolean_t
  308. bfa_ioc_ct_sync_start(struct bfa_ioc_s *ioc)
  309. {
  310. uint32_t r32 = readl(ioc->ioc_regs.ioc_fail_sync);
  311. uint32_t sync_reqd = bfa_ioc_ct_get_sync_reqd(r32);
  312. /*
  313. * Driver load time. If the sync required bit for this PCI fn
  314. * is set, it is due to an unclean exit by the driver for this
  315. * PCI fn in the previous incarnation. Whoever comes here first
  316. * should clean it up, no matter which PCI fn.
  317. */
  318. if (sync_reqd & bfa_ioc_ct_sync_pos(ioc)) {
  319. writel(0, ioc->ioc_regs.ioc_fail_sync);
  320. writel(1, ioc->ioc_regs.ioc_usage_reg);
  321. writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate);
  322. writel(BFI_IOC_UNINIT, ioc->ioc_regs.alt_ioc_fwstate);
  323. return BFA_TRUE;
  324. }
  325. return bfa_ioc_ct_sync_complete(ioc);
  326. }
  327. /*
  328. * Synchronized IOC failure processing routines
  329. */
  330. static void
  331. bfa_ioc_ct_sync_join(struct bfa_ioc_s *ioc)
  332. {
  333. uint32_t r32 = readl(ioc->ioc_regs.ioc_fail_sync);
  334. uint32_t sync_pos = bfa_ioc_ct_sync_reqd_pos(ioc);
  335. writel((r32 | sync_pos), ioc->ioc_regs.ioc_fail_sync);
  336. }
  337. static void
  338. bfa_ioc_ct_sync_leave(struct bfa_ioc_s *ioc)
  339. {
  340. uint32_t r32 = readl(ioc->ioc_regs.ioc_fail_sync);
  341. uint32_t sync_msk = bfa_ioc_ct_sync_reqd_pos(ioc) |
  342. bfa_ioc_ct_sync_pos(ioc);
  343. writel((r32 & ~sync_msk), ioc->ioc_regs.ioc_fail_sync);
  344. }
  345. static void
  346. bfa_ioc_ct_sync_ack(struct bfa_ioc_s *ioc)
  347. {
  348. uint32_t r32 = readl(ioc->ioc_regs.ioc_fail_sync);
  349. writel((r32 | bfa_ioc_ct_sync_pos(ioc)),
  350. ioc->ioc_regs.ioc_fail_sync);
  351. }
  352. static bfa_boolean_t
  353. bfa_ioc_ct_sync_complete(struct bfa_ioc_s *ioc)
  354. {
  355. uint32_t r32 = readl(ioc->ioc_regs.ioc_fail_sync);
  356. uint32_t sync_reqd = bfa_ioc_ct_get_sync_reqd(r32);
  357. uint32_t sync_ackd = bfa_ioc_ct_get_sync_ackd(r32);
  358. uint32_t tmp_ackd;
  359. if (sync_ackd == 0)
  360. return BFA_TRUE;
  361. /*
  362. * The check below is to see whether any other PCI fn
  363. * has reinitialized the ASIC (reset sync_ackd bits)
  364. * and failed again while this IOC was waiting for hw
  365. * semaphore (in bfa_iocpf_sm_semwait()).
  366. */
  367. tmp_ackd = sync_ackd;
  368. if ((sync_reqd & bfa_ioc_ct_sync_pos(ioc)) &&
  369. !(sync_ackd & bfa_ioc_ct_sync_pos(ioc)))
  370. sync_ackd |= bfa_ioc_ct_sync_pos(ioc);
  371. if (sync_reqd == sync_ackd) {
  372. writel(bfa_ioc_ct_clear_sync_ackd(r32),
  373. ioc->ioc_regs.ioc_fail_sync);
  374. writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
  375. writel(BFI_IOC_FAIL, ioc->ioc_regs.alt_ioc_fwstate);
  376. return BFA_TRUE;
  377. }
  378. /*
  379. * If another PCI fn reinitialized and failed again while
  380. * this IOC was waiting for hw sem, the sync_ackd bit for
  381. * this IOC need to be set again to allow reinitialization.
  382. */
  383. if (tmp_ackd != sync_ackd)
  384. writel((r32 | sync_ackd), ioc->ioc_regs.ioc_fail_sync);
  385. return BFA_FALSE;
  386. }
  387. /*
  388. * Check the firmware state to know if pll_init has been completed already
  389. */
  390. bfa_boolean_t
  391. bfa_ioc_ct_pll_init_complete(void __iomem *rb)
  392. {
  393. if ((readl(rb + BFA_IOC0_STATE_REG) == BFI_IOC_OP) ||
  394. (readl(rb + BFA_IOC1_STATE_REG) == BFI_IOC_OP))
  395. return BFA_TRUE;
  396. return BFA_FALSE;
  397. }
  398. bfa_status_t
  399. bfa_ioc_ct_pll_init(void __iomem *rb, bfa_boolean_t fcmode)
  400. {
  401. u32 pll_sclk, pll_fclk, r32;
  402. pll_sclk = __APP_PLL_312_LRESETN | __APP_PLL_312_ENARST |
  403. __APP_PLL_312_RSEL200500 | __APP_PLL_312_P0_1(3U) |
  404. __APP_PLL_312_JITLMT0_1(3U) |
  405. __APP_PLL_312_CNTLMT0_1(1U);
  406. pll_fclk = __APP_PLL_425_LRESETN | __APP_PLL_425_ENARST |
  407. __APP_PLL_425_RSEL200500 | __APP_PLL_425_P0_1(3U) |
  408. __APP_PLL_425_JITLMT0_1(3U) |
  409. __APP_PLL_425_CNTLMT0_1(1U);
  410. if (fcmode) {
  411. writel(0, (rb + OP_MODE));
  412. writel(__APP_EMS_CMLCKSEL | __APP_EMS_REFCKBUFEN2 |
  413. __APP_EMS_CHANNEL_SEL, (rb + ETH_MAC_SER_REG));
  414. } else {
  415. writel(__GLOBAL_FCOE_MODE, (rb + OP_MODE));
  416. writel(__APP_EMS_REFCKBUFEN1, (rb + ETH_MAC_SER_REG));
  417. }
  418. writel(BFI_IOC_UNINIT, (rb + BFA_IOC0_STATE_REG));
  419. writel(BFI_IOC_UNINIT, (rb + BFA_IOC1_STATE_REG));
  420. writel(0xffffffffU, (rb + HOSTFN0_INT_MSK));
  421. writel(0xffffffffU, (rb + HOSTFN1_INT_MSK));
  422. writel(0xffffffffU, (rb + HOSTFN0_INT_STATUS));
  423. writel(0xffffffffU, (rb + HOSTFN1_INT_STATUS));
  424. writel(0xffffffffU, (rb + HOSTFN0_INT_MSK));
  425. writel(0xffffffffU, (rb + HOSTFN1_INT_MSK));
  426. writel(pll_sclk | __APP_PLL_312_LOGIC_SOFT_RESET,
  427. rb + APP_PLL_312_CTL_REG);
  428. writel(pll_fclk | __APP_PLL_425_LOGIC_SOFT_RESET,
  429. rb + APP_PLL_425_CTL_REG);
  430. writel(pll_sclk | __APP_PLL_312_LOGIC_SOFT_RESET | __APP_PLL_312_ENABLE,
  431. rb + APP_PLL_312_CTL_REG);
  432. writel(pll_fclk | __APP_PLL_425_LOGIC_SOFT_RESET | __APP_PLL_425_ENABLE,
  433. rb + APP_PLL_425_CTL_REG);
  434. readl(rb + HOSTFN0_INT_MSK);
  435. udelay(2000);
  436. writel(0xffffffffU, (rb + HOSTFN0_INT_STATUS));
  437. writel(0xffffffffU, (rb + HOSTFN1_INT_STATUS));
  438. writel(pll_sclk | __APP_PLL_312_ENABLE, rb + APP_PLL_312_CTL_REG);
  439. writel(pll_fclk | __APP_PLL_425_ENABLE, rb + APP_PLL_425_CTL_REG);
  440. if (!fcmode) {
  441. writel(__PMM_1T_RESET_P, (rb + PMM_1T_RESET_REG_P0));
  442. writel(__PMM_1T_RESET_P, (rb + PMM_1T_RESET_REG_P1));
  443. }
  444. r32 = readl((rb + PSS_CTL_REG));
  445. r32 &= ~__PSS_LMEM_RESET;
  446. writel(r32, (rb + PSS_CTL_REG));
  447. udelay(1000);
  448. if (!fcmode) {
  449. writel(0, (rb + PMM_1T_RESET_REG_P0));
  450. writel(0, (rb + PMM_1T_RESET_REG_P1));
  451. }
  452. writel(__EDRAM_BISTR_START, (rb + MBIST_CTL_REG));
  453. udelay(1000);
  454. r32 = readl((rb + MBIST_STAT_REG));
  455. writel(0, (rb + MBIST_CTL_REG));
  456. return BFA_STATUS_OK;
  457. }