10a20de44SKrishna Gudipati /* 2a36c61f9SKrishna Gudipati * Copyright (c) 2005-2010 Brocade Communications Systems, Inc. 30a20de44SKrishna Gudipati * All rights reserved 40a20de44SKrishna Gudipati * www.brocade.com 50a20de44SKrishna Gudipati * 60a20de44SKrishna Gudipati * Linux driver for Brocade Fibre Channel Host Bus Adapter. 70a20de44SKrishna Gudipati * 80a20de44SKrishna Gudipati * This program is free software; you can redistribute it and/or modify it 90a20de44SKrishna Gudipati * under the terms of the GNU General Public License (GPL) Version 2 as 100a20de44SKrishna Gudipati * published by the Free Software Foundation 110a20de44SKrishna Gudipati * 120a20de44SKrishna Gudipati * This program is distributed in the hope that it will be useful, but 130a20de44SKrishna Gudipati * WITHOUT ANY WARRANTY; without even the implied warranty of 140a20de44SKrishna Gudipati * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 150a20de44SKrishna Gudipati * General Public License for more details. 160a20de44SKrishna Gudipati */ 170a20de44SKrishna Gudipati 18a36c61f9SKrishna Gudipati #include "bfa_ioc.h" 19a36c61f9SKrishna Gudipati #include "bfi_ctreg.h" 20a36c61f9SKrishna Gudipati #include "bfa_defs.h" 210a20de44SKrishna Gudipati 220a20de44SKrishna Gudipati BFA_TRC_FILE(CNA, IOC_CT); 230a20de44SKrishna Gudipati 240a20de44SKrishna Gudipati /* 250a20de44SKrishna Gudipati * forward declarations 260a20de44SKrishna Gudipati */ 270a20de44SKrishna Gudipati static bfa_boolean_t bfa_ioc_ct_firmware_lock(struct bfa_ioc_s *ioc); 280a20de44SKrishna Gudipati static void bfa_ioc_ct_firmware_unlock(struct bfa_ioc_s *ioc); 290a20de44SKrishna Gudipati static void bfa_ioc_ct_reg_init(struct bfa_ioc_s *ioc); 300a20de44SKrishna Gudipati static void bfa_ioc_ct_map_port(struct bfa_ioc_s *ioc); 310a20de44SKrishna Gudipati static void bfa_ioc_ct_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix); 320a20de44SKrishna Gudipati static void bfa_ioc_ct_notify_hbfail(struct bfa_ioc_s *ioc); 330a20de44SKrishna Gudipati static void bfa_ioc_ct_ownership_reset(struct bfa_ioc_s *ioc); 340a20de44SKrishna Gudipati 35*52f94b6fSMaggie static struct bfa_ioc_hwif_s hwif_ct; 360a20de44SKrishna Gudipati 375fbe25c7SJing Huang /* 380a20de44SKrishna Gudipati * Called from bfa_ioc_attach() to map asic specific calls. 390a20de44SKrishna Gudipati */ 400a20de44SKrishna Gudipati void 410a20de44SKrishna Gudipati bfa_ioc_set_ct_hwif(struct bfa_ioc_s *ioc) 420a20de44SKrishna Gudipati { 43293f82d5SJing Huang hwif_ct.ioc_pll_init = bfa_ioc_ct_pll_init; 44293f82d5SJing Huang hwif_ct.ioc_firmware_lock = bfa_ioc_ct_firmware_lock; 45293f82d5SJing Huang hwif_ct.ioc_firmware_unlock = bfa_ioc_ct_firmware_unlock; 46293f82d5SJing Huang hwif_ct.ioc_reg_init = bfa_ioc_ct_reg_init; 47293f82d5SJing Huang hwif_ct.ioc_map_port = bfa_ioc_ct_map_port; 48293f82d5SJing Huang hwif_ct.ioc_isr_mode_set = bfa_ioc_ct_isr_mode_set; 49293f82d5SJing Huang hwif_ct.ioc_notify_hbfail = bfa_ioc_ct_notify_hbfail; 50293f82d5SJing Huang hwif_ct.ioc_ownership_reset = bfa_ioc_ct_ownership_reset; 51293f82d5SJing Huang 520a20de44SKrishna Gudipati ioc->ioc_hwif = &hwif_ct; 530a20de44SKrishna Gudipati } 540a20de44SKrishna Gudipati 555fbe25c7SJing Huang /* 560a20de44SKrishna Gudipati * Return true if firmware of current driver matches the running firmware. 570a20de44SKrishna Gudipati */ 580a20de44SKrishna Gudipati static bfa_boolean_t 590a20de44SKrishna Gudipati bfa_ioc_ct_firmware_lock(struct bfa_ioc_s *ioc) 600a20de44SKrishna Gudipati { 610a20de44SKrishna Gudipati enum bfi_ioc_state ioc_fwstate; 62d1c61f8eSKrishna Gudipati u32 usecnt; 630a20de44SKrishna Gudipati struct bfi_ioc_image_hdr_s fwhdr; 640a20de44SKrishna Gudipati 655fbe25c7SJing Huang /* 660a20de44SKrishna Gudipati * Firmware match check is relevant only for CNA. 670a20de44SKrishna Gudipati */ 680a20de44SKrishna Gudipati if (!ioc->cna) 690a20de44SKrishna Gudipati return BFA_TRUE; 700a20de44SKrishna Gudipati 715fbe25c7SJing Huang /* 720a20de44SKrishna Gudipati * If bios boot (flash based) -- do not increment usage count 730a20de44SKrishna Gudipati */ 74a36c61f9SKrishna Gudipati if (bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)) < 75a36c61f9SKrishna Gudipati BFA_IOC_FWIMG_MINSZ) 760a20de44SKrishna Gudipati return BFA_TRUE; 770a20de44SKrishna Gudipati 780a20de44SKrishna Gudipati bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg); 7953440260SJing Huang usecnt = readl(ioc->ioc_regs.ioc_usage_reg); 800a20de44SKrishna Gudipati 815fbe25c7SJing Huang /* 820a20de44SKrishna Gudipati * If usage count is 0, always return TRUE. 830a20de44SKrishna Gudipati */ 840a20de44SKrishna Gudipati if (usecnt == 0) { 8553440260SJing Huang writel(1, ioc->ioc_regs.ioc_usage_reg); 860a20de44SKrishna Gudipati bfa_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg); 870a20de44SKrishna Gudipati bfa_trc(ioc, usecnt); 880a20de44SKrishna Gudipati return BFA_TRUE; 890a20de44SKrishna Gudipati } 900a20de44SKrishna Gudipati 9153440260SJing Huang ioc_fwstate = readl(ioc->ioc_regs.ioc_fwstate); 920a20de44SKrishna Gudipati bfa_trc(ioc, ioc_fwstate); 930a20de44SKrishna Gudipati 945fbe25c7SJing Huang /* 950a20de44SKrishna Gudipati * Use count cannot be non-zero and chip in uninitialized state. 960a20de44SKrishna Gudipati */ 970a20de44SKrishna Gudipati bfa_assert(ioc_fwstate != BFI_IOC_UNINIT); 980a20de44SKrishna Gudipati 995fbe25c7SJing Huang /* 1000a20de44SKrishna Gudipati * Check if another driver with a different firmware is active 1010a20de44SKrishna Gudipati */ 1020a20de44SKrishna Gudipati bfa_ioc_fwver_get(ioc, &fwhdr); 1030a20de44SKrishna Gudipati if (!bfa_ioc_fwver_cmp(ioc, &fwhdr)) { 1040a20de44SKrishna Gudipati bfa_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg); 1050a20de44SKrishna Gudipati bfa_trc(ioc, usecnt); 1060a20de44SKrishna Gudipati return BFA_FALSE; 1070a20de44SKrishna Gudipati } 1080a20de44SKrishna Gudipati 1095fbe25c7SJing Huang /* 1100a20de44SKrishna Gudipati * Same firmware version. Increment the reference count. 1110a20de44SKrishna Gudipati */ 1120a20de44SKrishna Gudipati usecnt++; 11353440260SJing Huang writel(usecnt, ioc->ioc_regs.ioc_usage_reg); 1140a20de44SKrishna Gudipati bfa_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg); 1150a20de44SKrishna Gudipati bfa_trc(ioc, usecnt); 1160a20de44SKrishna Gudipati return BFA_TRUE; 1170a20de44SKrishna Gudipati } 1180a20de44SKrishna Gudipati 1190a20de44SKrishna Gudipati static void 1200a20de44SKrishna Gudipati bfa_ioc_ct_firmware_unlock(struct bfa_ioc_s *ioc) 1210a20de44SKrishna Gudipati { 122d1c61f8eSKrishna Gudipati u32 usecnt; 1230a20de44SKrishna Gudipati 1245fbe25c7SJing Huang /* 1250a20de44SKrishna Gudipati * Firmware lock is relevant only for CNA. 126293f82d5SJing Huang */ 127293f82d5SJing Huang if (!ioc->cna) 128293f82d5SJing Huang return; 129293f82d5SJing Huang 1305fbe25c7SJing Huang /* 1310a20de44SKrishna Gudipati * If bios boot (flash based) -- do not decrement usage count 1320a20de44SKrishna Gudipati */ 133a36c61f9SKrishna Gudipati if (bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)) < 134a36c61f9SKrishna Gudipati BFA_IOC_FWIMG_MINSZ) 1350a20de44SKrishna Gudipati return; 1360a20de44SKrishna Gudipati 1375fbe25c7SJing Huang /* 1380a20de44SKrishna Gudipati * decrement usage count 1390a20de44SKrishna Gudipati */ 1400a20de44SKrishna Gudipati bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg); 14153440260SJing Huang usecnt = readl(ioc->ioc_regs.ioc_usage_reg); 1420a20de44SKrishna Gudipati bfa_assert(usecnt > 0); 1430a20de44SKrishna Gudipati 1440a20de44SKrishna Gudipati usecnt--; 14553440260SJing Huang writel(usecnt, ioc->ioc_regs.ioc_usage_reg); 1460a20de44SKrishna Gudipati bfa_trc(ioc, usecnt); 1470a20de44SKrishna Gudipati 1480a20de44SKrishna Gudipati bfa_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg); 1490a20de44SKrishna Gudipati } 1500a20de44SKrishna Gudipati 1515fbe25c7SJing Huang /* 1520a20de44SKrishna Gudipati * Notify other functions on HB failure. 1530a20de44SKrishna Gudipati */ 1540a20de44SKrishna Gudipati static void 1550a20de44SKrishna Gudipati bfa_ioc_ct_notify_hbfail(struct bfa_ioc_s *ioc) 1560a20de44SKrishna Gudipati { 157816e49b8SKrishna Gudipati if (ioc->cna) { 15853440260SJing Huang writel(__FW_INIT_HALT_P, ioc->ioc_regs.ll_halt); 1590a20de44SKrishna Gudipati /* Wait for halt to take effect */ 16053440260SJing Huang readl(ioc->ioc_regs.ll_halt); 161816e49b8SKrishna Gudipati } else { 16253440260SJing Huang writel(__PSS_ERR_STATUS_SET, ioc->ioc_regs.err_set); 16353440260SJing Huang readl(ioc->ioc_regs.err_set); 164816e49b8SKrishna Gudipati } 1650a20de44SKrishna Gudipati } 1660a20de44SKrishna Gudipati 1675fbe25c7SJing Huang /* 1680a20de44SKrishna Gudipati * Host to LPU mailbox message addresses 1690a20de44SKrishna Gudipati */ 170d1c61f8eSKrishna Gudipati static struct { u32 hfn_mbox, lpu_mbox, hfn_pgn; } iocreg_fnreg[] = { 1710a20de44SKrishna Gudipati { HOSTFN0_LPU_MBOX0_0, LPU_HOSTFN0_MBOX0_0, HOST_PAGE_NUM_FN0 }, 1720a20de44SKrishna Gudipati { HOSTFN1_LPU_MBOX0_8, LPU_HOSTFN1_MBOX0_8, HOST_PAGE_NUM_FN1 }, 1730a20de44SKrishna Gudipati { HOSTFN2_LPU_MBOX0_0, LPU_HOSTFN2_MBOX0_0, HOST_PAGE_NUM_FN2 }, 1740a20de44SKrishna Gudipati { HOSTFN3_LPU_MBOX0_8, LPU_HOSTFN3_MBOX0_8, HOST_PAGE_NUM_FN3 } 1750a20de44SKrishna Gudipati }; 1760a20de44SKrishna Gudipati 1775fbe25c7SJing Huang /* 1780a20de44SKrishna Gudipati * Host <-> LPU mailbox command/status registers - port 0 1790a20de44SKrishna Gudipati */ 180d1c61f8eSKrishna Gudipati static struct { u32 hfn, lpu; } iocreg_mbcmd_p0[] = { 1810a20de44SKrishna Gudipati { HOSTFN0_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN0_MBOX0_CMD_STAT }, 1820a20de44SKrishna Gudipati { HOSTFN1_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN1_MBOX0_CMD_STAT }, 1830a20de44SKrishna Gudipati { HOSTFN2_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN2_MBOX0_CMD_STAT }, 1840a20de44SKrishna Gudipati { HOSTFN3_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN3_MBOX0_CMD_STAT } 1850a20de44SKrishna Gudipati }; 1860a20de44SKrishna Gudipati 1875fbe25c7SJing Huang /* 1880a20de44SKrishna Gudipati * Host <-> LPU mailbox command/status registers - port 1 1890a20de44SKrishna Gudipati */ 190d1c61f8eSKrishna Gudipati static struct { u32 hfn, lpu; } iocreg_mbcmd_p1[] = { 1910a20de44SKrishna Gudipati { HOSTFN0_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN0_MBOX0_CMD_STAT }, 1920a20de44SKrishna Gudipati { HOSTFN1_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN1_MBOX0_CMD_STAT }, 1930a20de44SKrishna Gudipati { HOSTFN2_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN2_MBOX0_CMD_STAT }, 1940a20de44SKrishna Gudipati { HOSTFN3_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN3_MBOX0_CMD_STAT } 1950a20de44SKrishna Gudipati }; 1960a20de44SKrishna Gudipati 1970a20de44SKrishna Gudipati static void 1980a20de44SKrishna Gudipati bfa_ioc_ct_reg_init(struct bfa_ioc_s *ioc) 1990a20de44SKrishna Gudipati { 20053440260SJing Huang void __iomem *rb; 2010a20de44SKrishna Gudipati int pcifn = bfa_ioc_pcifn(ioc); 2020a20de44SKrishna Gudipati 2030a20de44SKrishna Gudipati rb = bfa_ioc_bar0(ioc); 2040a20de44SKrishna Gudipati 2050a20de44SKrishna Gudipati ioc->ioc_regs.hfn_mbox = rb + iocreg_fnreg[pcifn].hfn_mbox; 2060a20de44SKrishna Gudipati ioc->ioc_regs.lpu_mbox = rb + iocreg_fnreg[pcifn].lpu_mbox; 2070a20de44SKrishna Gudipati ioc->ioc_regs.host_page_num_fn = rb + iocreg_fnreg[pcifn].hfn_pgn; 2080a20de44SKrishna Gudipati 2090a20de44SKrishna Gudipati if (ioc->port_id == 0) { 2100a20de44SKrishna Gudipati ioc->ioc_regs.heartbeat = rb + BFA_IOC0_HBEAT_REG; 2110a20de44SKrishna Gudipati ioc->ioc_regs.ioc_fwstate = rb + BFA_IOC0_STATE_REG; 2120a20de44SKrishna Gudipati ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd_p0[pcifn].hfn; 2130a20de44SKrishna Gudipati ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd_p0[pcifn].lpu; 2140a20de44SKrishna Gudipati ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P0; 2150a20de44SKrishna Gudipati } else { 2160a20de44SKrishna Gudipati ioc->ioc_regs.heartbeat = (rb + BFA_IOC1_HBEAT_REG); 2170a20de44SKrishna Gudipati ioc->ioc_regs.ioc_fwstate = (rb + BFA_IOC1_STATE_REG); 2180a20de44SKrishna Gudipati ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd_p1[pcifn].hfn; 2190a20de44SKrishna Gudipati ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd_p1[pcifn].lpu; 2200a20de44SKrishna Gudipati ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P1; 2210a20de44SKrishna Gudipati } 2220a20de44SKrishna Gudipati 2230a20de44SKrishna Gudipati /* 2240a20de44SKrishna Gudipati * PSS control registers 2250a20de44SKrishna Gudipati */ 2260a20de44SKrishna Gudipati ioc->ioc_regs.pss_ctl_reg = (rb + PSS_CTL_REG); 2278b651b42SKrishna Gudipati ioc->ioc_regs.pss_err_status_reg = (rb + PSS_ERR_STATUS_REG); 2280a20de44SKrishna Gudipati ioc->ioc_regs.app_pll_fast_ctl_reg = (rb + APP_PLL_425_CTL_REG); 2290a20de44SKrishna Gudipati ioc->ioc_regs.app_pll_slow_ctl_reg = (rb + APP_PLL_312_CTL_REG); 2300a20de44SKrishna Gudipati 2310a20de44SKrishna Gudipati /* 2320a20de44SKrishna Gudipati * IOC semaphore registers and serialization 2330a20de44SKrishna Gudipati */ 2340a20de44SKrishna Gudipati ioc->ioc_regs.ioc_sem_reg = (rb + HOST_SEM0_REG); 2350a20de44SKrishna Gudipati ioc->ioc_regs.ioc_usage_sem_reg = (rb + HOST_SEM1_REG); 2360a20de44SKrishna Gudipati ioc->ioc_regs.ioc_init_sem_reg = (rb + HOST_SEM2_REG); 2370a20de44SKrishna Gudipati ioc->ioc_regs.ioc_usage_reg = (rb + BFA_FW_USE_COUNT); 2380a20de44SKrishna Gudipati 2395fbe25c7SJing Huang /* 2400a20de44SKrishna Gudipati * sram memory access 2410a20de44SKrishna Gudipati */ 2420a20de44SKrishna Gudipati ioc->ioc_regs.smem_page_start = (rb + PSS_SMEM_PAGE_START); 2430a20de44SKrishna Gudipati ioc->ioc_regs.smem_pg0 = BFI_IOC_SMEM_PG0_CT; 244816e49b8SKrishna Gudipati 245816e49b8SKrishna Gudipati /* 246816e49b8SKrishna Gudipati * err set reg : for notification of hb failure in fcmode 247816e49b8SKrishna Gudipati */ 248816e49b8SKrishna Gudipati ioc->ioc_regs.err_set = (rb + ERR_SET_REG); 2490a20de44SKrishna Gudipati } 2500a20de44SKrishna Gudipati 2515fbe25c7SJing Huang /* 2520a20de44SKrishna Gudipati * Initialize IOC to port mapping. 2530a20de44SKrishna Gudipati */ 2540a20de44SKrishna Gudipati 2550a20de44SKrishna Gudipati #define FNC_PERS_FN_SHIFT(__fn) ((__fn) * 8) 2560a20de44SKrishna Gudipati static void 2570a20de44SKrishna Gudipati bfa_ioc_ct_map_port(struct bfa_ioc_s *ioc) 2580a20de44SKrishna Gudipati { 25953440260SJing Huang void __iomem *rb = ioc->pcidev.pci_bar_kva; 260d1c61f8eSKrishna Gudipati u32 r32; 2610a20de44SKrishna Gudipati 2625fbe25c7SJing Huang /* 2630a20de44SKrishna Gudipati * For catapult, base port id on personality register and IOC type 2640a20de44SKrishna Gudipati */ 26553440260SJing Huang r32 = readl(rb + FNC_PERS_REG); 2660a20de44SKrishna Gudipati r32 >>= FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc)); 2670a20de44SKrishna Gudipati ioc->port_id = (r32 & __F0_PORT_MAP_MK) >> __F0_PORT_MAP_SH; 2680a20de44SKrishna Gudipati 2690a20de44SKrishna Gudipati bfa_trc(ioc, bfa_ioc_pcifn(ioc)); 2700a20de44SKrishna Gudipati bfa_trc(ioc, ioc->port_id); 2710a20de44SKrishna Gudipati } 2720a20de44SKrishna Gudipati 2735fbe25c7SJing Huang /* 2740a20de44SKrishna Gudipati * Set interrupt mode for a function: INTX or MSIX 2750a20de44SKrishna Gudipati */ 2760a20de44SKrishna Gudipati static void 2770a20de44SKrishna Gudipati bfa_ioc_ct_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix) 2780a20de44SKrishna Gudipati { 27953440260SJing Huang void __iomem *rb = ioc->pcidev.pci_bar_kva; 280d1c61f8eSKrishna Gudipati u32 r32, mode; 2810a20de44SKrishna Gudipati 28253440260SJing Huang r32 = readl(rb + FNC_PERS_REG); 2830a20de44SKrishna Gudipati bfa_trc(ioc, r32); 2840a20de44SKrishna Gudipati 2850a20de44SKrishna Gudipati mode = (r32 >> FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc))) & 2860a20de44SKrishna Gudipati __F0_INTX_STATUS; 2870a20de44SKrishna Gudipati 2885fbe25c7SJing Huang /* 2890a20de44SKrishna Gudipati * If already in desired mode, do not change anything 2900a20de44SKrishna Gudipati */ 2910a20de44SKrishna Gudipati if (!msix && mode) 2920a20de44SKrishna Gudipati return; 2930a20de44SKrishna Gudipati 2940a20de44SKrishna Gudipati if (msix) 2950a20de44SKrishna Gudipati mode = __F0_INTX_STATUS_MSIX; 2960a20de44SKrishna Gudipati else 2970a20de44SKrishna Gudipati mode = __F0_INTX_STATUS_INTA; 2980a20de44SKrishna Gudipati 2990a20de44SKrishna Gudipati r32 &= ~(__F0_INTX_STATUS << FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc))); 3000a20de44SKrishna Gudipati r32 |= (mode << FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc))); 3010a20de44SKrishna Gudipati bfa_trc(ioc, r32); 3020a20de44SKrishna Gudipati 30353440260SJing Huang writel(r32, rb + FNC_PERS_REG); 3040a20de44SKrishna Gudipati } 3050a20de44SKrishna Gudipati 3065fbe25c7SJing Huang /* 3070a20de44SKrishna Gudipati * Cleanup hw semaphore and usecnt registers 3080a20de44SKrishna Gudipati */ 3090a20de44SKrishna Gudipati static void 3100a20de44SKrishna Gudipati bfa_ioc_ct_ownership_reset(struct bfa_ioc_s *ioc) 3110a20de44SKrishna Gudipati { 3120a20de44SKrishna Gudipati 3130a20de44SKrishna Gudipati if (ioc->cna) { 3140a20de44SKrishna Gudipati bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg); 31553440260SJing Huang writel(0, ioc->ioc_regs.ioc_usage_reg); 3160a20de44SKrishna Gudipati bfa_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg); 3170a20de44SKrishna Gudipati } 3180a20de44SKrishna Gudipati 3190a20de44SKrishna Gudipati /* 3200a20de44SKrishna Gudipati * Read the hw sem reg to make sure that it is locked 3210a20de44SKrishna Gudipati * before we clear it. If it is not locked, writing 1 3220a20de44SKrishna Gudipati * will lock it instead of clearing it. 3230a20de44SKrishna Gudipati */ 32453440260SJing Huang readl(ioc->ioc_regs.ioc_sem_reg); 3250a20de44SKrishna Gudipati bfa_ioc_hw_sem_release(ioc); 3260a20de44SKrishna Gudipati } 327a36c61f9SKrishna Gudipati 328a36c61f9SKrishna Gudipati 329a36c61f9SKrishna Gudipati 330a36c61f9SKrishna Gudipati /* 331a36c61f9SKrishna Gudipati * Check the firmware state to know if pll_init has been completed already 332a36c61f9SKrishna Gudipati */ 333a36c61f9SKrishna Gudipati bfa_boolean_t 33453440260SJing Huang bfa_ioc_ct_pll_init_complete(void __iomem *rb) 335a36c61f9SKrishna Gudipati { 33653440260SJing Huang if ((readl(rb + BFA_IOC0_STATE_REG) == BFI_IOC_OP) || 33753440260SJing Huang (readl(rb + BFA_IOC1_STATE_REG) == BFI_IOC_OP)) 338a36c61f9SKrishna Gudipati return BFA_TRUE; 339a36c61f9SKrishna Gudipati 340a36c61f9SKrishna Gudipati return BFA_FALSE; 341a36c61f9SKrishna Gudipati } 342a36c61f9SKrishna Gudipati 343a36c61f9SKrishna Gudipati bfa_status_t 34453440260SJing Huang bfa_ioc_ct_pll_init(void __iomem *rb, bfa_boolean_t fcmode) 345a36c61f9SKrishna Gudipati { 346a36c61f9SKrishna Gudipati u32 pll_sclk, pll_fclk, r32; 347a36c61f9SKrishna Gudipati 348a36c61f9SKrishna Gudipati pll_sclk = __APP_PLL_312_LRESETN | __APP_PLL_312_ENARST | 349a36c61f9SKrishna Gudipati __APP_PLL_312_RSEL200500 | __APP_PLL_312_P0_1(3U) | 350a36c61f9SKrishna Gudipati __APP_PLL_312_JITLMT0_1(3U) | 351a36c61f9SKrishna Gudipati __APP_PLL_312_CNTLMT0_1(1U); 352a36c61f9SKrishna Gudipati pll_fclk = __APP_PLL_425_LRESETN | __APP_PLL_425_ENARST | 353a36c61f9SKrishna Gudipati __APP_PLL_425_RSEL200500 | __APP_PLL_425_P0_1(3U) | 354a36c61f9SKrishna Gudipati __APP_PLL_425_JITLMT0_1(3U) | 355a36c61f9SKrishna Gudipati __APP_PLL_425_CNTLMT0_1(1U); 356a36c61f9SKrishna Gudipati if (fcmode) { 35753440260SJing Huang writel(0, (rb + OP_MODE)); 35853440260SJing Huang writel(__APP_EMS_CMLCKSEL | __APP_EMS_REFCKBUFEN2 | 35953440260SJing Huang __APP_EMS_CHANNEL_SEL, (rb + ETH_MAC_SER_REG)); 360a36c61f9SKrishna Gudipati } else { 36153440260SJing Huang writel(__GLOBAL_FCOE_MODE, (rb + OP_MODE)); 36253440260SJing Huang writel(__APP_EMS_REFCKBUFEN1, (rb + ETH_MAC_SER_REG)); 363a36c61f9SKrishna Gudipati } 36453440260SJing Huang writel(BFI_IOC_UNINIT, (rb + BFA_IOC0_STATE_REG)); 36553440260SJing Huang writel(BFI_IOC_UNINIT, (rb + BFA_IOC1_STATE_REG)); 36653440260SJing Huang writel(0xffffffffU, (rb + HOSTFN0_INT_MSK)); 36753440260SJing Huang writel(0xffffffffU, (rb + HOSTFN1_INT_MSK)); 36853440260SJing Huang writel(0xffffffffU, (rb + HOSTFN0_INT_STATUS)); 36953440260SJing Huang writel(0xffffffffU, (rb + HOSTFN1_INT_STATUS)); 37053440260SJing Huang writel(0xffffffffU, (rb + HOSTFN0_INT_MSK)); 37153440260SJing Huang writel(0xffffffffU, (rb + HOSTFN1_INT_MSK)); 37253440260SJing Huang writel(pll_sclk | __APP_PLL_312_LOGIC_SOFT_RESET, 37353440260SJing Huang rb + APP_PLL_312_CTL_REG); 37453440260SJing Huang writel(pll_fclk | __APP_PLL_425_LOGIC_SOFT_RESET, 37553440260SJing Huang rb + APP_PLL_425_CTL_REG); 37653440260SJing Huang writel(pll_sclk | __APP_PLL_312_LOGIC_SOFT_RESET | __APP_PLL_312_ENABLE, 37753440260SJing Huang rb + APP_PLL_312_CTL_REG); 37853440260SJing Huang writel(pll_fclk | __APP_PLL_425_LOGIC_SOFT_RESET | __APP_PLL_425_ENABLE, 37953440260SJing Huang rb + APP_PLL_425_CTL_REG); 38053440260SJing Huang readl(rb + HOSTFN0_INT_MSK); 3816a18b167SJing Huang udelay(2000); 38253440260SJing Huang writel(0xffffffffU, (rb + HOSTFN0_INT_STATUS)); 38353440260SJing Huang writel(0xffffffffU, (rb + HOSTFN1_INT_STATUS)); 38453440260SJing Huang writel(pll_sclk | __APP_PLL_312_ENABLE, rb + APP_PLL_312_CTL_REG); 38553440260SJing Huang writel(pll_fclk | __APP_PLL_425_ENABLE, rb + APP_PLL_425_CTL_REG); 386a36c61f9SKrishna Gudipati if (!fcmode) { 38753440260SJing Huang writel(__PMM_1T_RESET_P, (rb + PMM_1T_RESET_REG_P0)); 38853440260SJing Huang writel(__PMM_1T_RESET_P, (rb + PMM_1T_RESET_REG_P1)); 389a36c61f9SKrishna Gudipati } 39053440260SJing Huang r32 = readl((rb + PSS_CTL_REG)); 391a36c61f9SKrishna Gudipati r32 &= ~__PSS_LMEM_RESET; 39253440260SJing Huang writel(r32, (rb + PSS_CTL_REG)); 3936a18b167SJing Huang udelay(1000); 394a36c61f9SKrishna Gudipati if (!fcmode) { 39553440260SJing Huang writel(0, (rb + PMM_1T_RESET_REG_P0)); 39653440260SJing Huang writel(0, (rb + PMM_1T_RESET_REG_P1)); 397a36c61f9SKrishna Gudipati } 398a36c61f9SKrishna Gudipati 39953440260SJing Huang writel(__EDRAM_BISTR_START, (rb + MBIST_CTL_REG)); 4006a18b167SJing Huang udelay(1000); 40153440260SJing Huang r32 = readl((rb + MBIST_STAT_REG)); 40253440260SJing Huang writel(0, (rb + MBIST_CTL_REG)); 403a36c61f9SKrishna Gudipati return BFA_STATUS_OK; 404a36c61f9SKrishna Gudipati } 405