10a20de44SKrishna Gudipati /* 2*a36c61f9SKrishna 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 18*a36c61f9SKrishna Gudipati #include "bfa_ioc.h" 19*a36c61f9SKrishna Gudipati #include "bfi_cbreg.h" 20*a36c61f9SKrishna Gudipati #include "bfa_defs.h" 210a20de44SKrishna Gudipati 220a20de44SKrishna Gudipati BFA_TRC_FILE(CNA, IOC_CB); 230a20de44SKrishna Gudipati 240a20de44SKrishna Gudipati /* 250a20de44SKrishna Gudipati * forward declarations 260a20de44SKrishna Gudipati */ 270a20de44SKrishna Gudipati static bfa_boolean_t bfa_ioc_cb_firmware_lock(struct bfa_ioc_s *ioc); 280a20de44SKrishna Gudipati static void bfa_ioc_cb_firmware_unlock(struct bfa_ioc_s *ioc); 290a20de44SKrishna Gudipati static void bfa_ioc_cb_reg_init(struct bfa_ioc_s *ioc); 300a20de44SKrishna Gudipati static void bfa_ioc_cb_map_port(struct bfa_ioc_s *ioc); 310a20de44SKrishna Gudipati static void bfa_ioc_cb_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix); 320a20de44SKrishna Gudipati static void bfa_ioc_cb_notify_hbfail(struct bfa_ioc_s *ioc); 330a20de44SKrishna Gudipati static void bfa_ioc_cb_ownership_reset(struct bfa_ioc_s *ioc); 340a20de44SKrishna Gudipati 35293f82d5SJing Huang struct bfa_ioc_hwif_s hwif_cb; 360a20de44SKrishna Gudipati 370a20de44SKrishna Gudipati /** 380a20de44SKrishna Gudipati * Called from bfa_ioc_attach() to map asic specific calls. 390a20de44SKrishna Gudipati */ 400a20de44SKrishna Gudipati void 410a20de44SKrishna Gudipati bfa_ioc_set_cb_hwif(struct bfa_ioc_s *ioc) 420a20de44SKrishna Gudipati { 43293f82d5SJing Huang hwif_cb.ioc_pll_init = bfa_ioc_cb_pll_init; 44293f82d5SJing Huang hwif_cb.ioc_firmware_lock = bfa_ioc_cb_firmware_lock; 45293f82d5SJing Huang hwif_cb.ioc_firmware_unlock = bfa_ioc_cb_firmware_unlock; 46293f82d5SJing Huang hwif_cb.ioc_reg_init = bfa_ioc_cb_reg_init; 47293f82d5SJing Huang hwif_cb.ioc_map_port = bfa_ioc_cb_map_port; 48293f82d5SJing Huang hwif_cb.ioc_isr_mode_set = bfa_ioc_cb_isr_mode_set; 49293f82d5SJing Huang hwif_cb.ioc_notify_hbfail = bfa_ioc_cb_notify_hbfail; 50293f82d5SJing Huang hwif_cb.ioc_ownership_reset = bfa_ioc_cb_ownership_reset; 51293f82d5SJing Huang 520a20de44SKrishna Gudipati ioc->ioc_hwif = &hwif_cb; 530a20de44SKrishna Gudipati } 540a20de44SKrishna Gudipati 550a20de44SKrishna Gudipati /** 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_cb_firmware_lock(struct bfa_ioc_s *ioc) 600a20de44SKrishna Gudipati { 610a20de44SKrishna Gudipati return BFA_TRUE; 620a20de44SKrishna Gudipati } 630a20de44SKrishna Gudipati 640a20de44SKrishna Gudipati static void 650a20de44SKrishna Gudipati bfa_ioc_cb_firmware_unlock(struct bfa_ioc_s *ioc) 660a20de44SKrishna Gudipati { 670a20de44SKrishna Gudipati } 680a20de44SKrishna Gudipati 690a20de44SKrishna Gudipati /** 700a20de44SKrishna Gudipati * Notify other functions on HB failure. 710a20de44SKrishna Gudipati */ 720a20de44SKrishna Gudipati static void 730a20de44SKrishna Gudipati bfa_ioc_cb_notify_hbfail(struct bfa_ioc_s *ioc) 740a20de44SKrishna Gudipati { 750a20de44SKrishna Gudipati bfa_reg_write(ioc->ioc_regs.err_set, __PSS_ERR_STATUS_SET); 760a20de44SKrishna Gudipati bfa_reg_read(ioc->ioc_regs.err_set); 770a20de44SKrishna Gudipati } 780a20de44SKrishna Gudipati 790a20de44SKrishna Gudipati /** 800a20de44SKrishna Gudipati * Host to LPU mailbox message addresses 810a20de44SKrishna Gudipati */ 82d1c61f8eSKrishna Gudipati static struct { u32 hfn_mbox, lpu_mbox, hfn_pgn; } iocreg_fnreg[] = { 830a20de44SKrishna Gudipati { HOSTFN0_LPU_MBOX0_0, LPU_HOSTFN0_MBOX0_0, HOST_PAGE_NUM_FN0 }, 840a20de44SKrishna Gudipati { HOSTFN1_LPU_MBOX0_8, LPU_HOSTFN1_MBOX0_8, HOST_PAGE_NUM_FN1 } 850a20de44SKrishna Gudipati }; 860a20de44SKrishna Gudipati 870a20de44SKrishna Gudipati /** 880a20de44SKrishna Gudipati * Host <-> LPU mailbox command/status registers 890a20de44SKrishna Gudipati */ 90d1c61f8eSKrishna Gudipati static struct { u32 hfn, lpu; } iocreg_mbcmd[] = { 91*a36c61f9SKrishna Gudipati 920a20de44SKrishna Gudipati { HOSTFN0_LPU0_CMD_STAT, LPU0_HOSTFN0_CMD_STAT }, 930a20de44SKrishna Gudipati { HOSTFN1_LPU1_CMD_STAT, LPU1_HOSTFN1_CMD_STAT } 940a20de44SKrishna Gudipati }; 950a20de44SKrishna Gudipati 960a20de44SKrishna Gudipati static void 970a20de44SKrishna Gudipati bfa_ioc_cb_reg_init(struct bfa_ioc_s *ioc) 980a20de44SKrishna Gudipati { 990a20de44SKrishna Gudipati bfa_os_addr_t rb; 1000a20de44SKrishna Gudipati int pcifn = bfa_ioc_pcifn(ioc); 1010a20de44SKrishna Gudipati 1020a20de44SKrishna Gudipati rb = bfa_ioc_bar0(ioc); 1030a20de44SKrishna Gudipati 1040a20de44SKrishna Gudipati ioc->ioc_regs.hfn_mbox = rb + iocreg_fnreg[pcifn].hfn_mbox; 1050a20de44SKrishna Gudipati ioc->ioc_regs.lpu_mbox = rb + iocreg_fnreg[pcifn].lpu_mbox; 1060a20de44SKrishna Gudipati ioc->ioc_regs.host_page_num_fn = rb + iocreg_fnreg[pcifn].hfn_pgn; 1070a20de44SKrishna Gudipati 1080a20de44SKrishna Gudipati if (ioc->port_id == 0) { 1090a20de44SKrishna Gudipati ioc->ioc_regs.heartbeat = rb + BFA_IOC0_HBEAT_REG; 1100a20de44SKrishna Gudipati ioc->ioc_regs.ioc_fwstate = rb + BFA_IOC0_STATE_REG; 1110a20de44SKrishna Gudipati } else { 1120a20de44SKrishna Gudipati ioc->ioc_regs.heartbeat = (rb + BFA_IOC1_HBEAT_REG); 1130a20de44SKrishna Gudipati ioc->ioc_regs.ioc_fwstate = (rb + BFA_IOC1_STATE_REG); 1140a20de44SKrishna Gudipati } 1150a20de44SKrishna Gudipati 1160a20de44SKrishna Gudipati /** 1170a20de44SKrishna Gudipati * Host <-> LPU mailbox command/status registers 1180a20de44SKrishna Gudipati */ 1190a20de44SKrishna Gudipati ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd[pcifn].hfn; 1200a20de44SKrishna Gudipati ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd[pcifn].lpu; 1210a20de44SKrishna Gudipati 1220a20de44SKrishna Gudipati /* 1230a20de44SKrishna Gudipati * PSS control registers 1240a20de44SKrishna Gudipati */ 1250a20de44SKrishna Gudipati ioc->ioc_regs.pss_ctl_reg = (rb + PSS_CTL_REG); 1268b651b42SKrishna Gudipati ioc->ioc_regs.pss_err_status_reg = (rb + PSS_ERR_STATUS_REG); 1270a20de44SKrishna Gudipati ioc->ioc_regs.app_pll_fast_ctl_reg = (rb + APP_PLL_400_CTL_REG); 1280a20de44SKrishna Gudipati ioc->ioc_regs.app_pll_slow_ctl_reg = (rb + APP_PLL_212_CTL_REG); 1290a20de44SKrishna Gudipati 1300a20de44SKrishna Gudipati /* 1310a20de44SKrishna Gudipati * IOC semaphore registers and serialization 1320a20de44SKrishna Gudipati */ 1330a20de44SKrishna Gudipati ioc->ioc_regs.ioc_sem_reg = (rb + HOST_SEM0_REG); 1340a20de44SKrishna Gudipati ioc->ioc_regs.ioc_init_sem_reg = (rb + HOST_SEM2_REG); 1350a20de44SKrishna Gudipati 1360a20de44SKrishna Gudipati /** 1370a20de44SKrishna Gudipati * sram memory access 1380a20de44SKrishna Gudipati */ 1390a20de44SKrishna Gudipati ioc->ioc_regs.smem_page_start = (rb + PSS_SMEM_PAGE_START); 1400a20de44SKrishna Gudipati ioc->ioc_regs.smem_pg0 = BFI_IOC_SMEM_PG0_CB; 1410a20de44SKrishna Gudipati 1420a20de44SKrishna Gudipati /* 1430a20de44SKrishna Gudipati * err set reg : for notification of hb failure 1440a20de44SKrishna Gudipati */ 1450a20de44SKrishna Gudipati ioc->ioc_regs.err_set = (rb + ERR_SET_REG); 1460a20de44SKrishna Gudipati } 1470a20de44SKrishna Gudipati 1480a20de44SKrishna Gudipati /** 1490a20de44SKrishna Gudipati * Initialize IOC to port mapping. 1500a20de44SKrishna Gudipati */ 151*a36c61f9SKrishna Gudipati 1520a20de44SKrishna Gudipati static void 1530a20de44SKrishna Gudipati bfa_ioc_cb_map_port(struct bfa_ioc_s *ioc) 1540a20de44SKrishna Gudipati { 1550a20de44SKrishna Gudipati /** 1560a20de44SKrishna Gudipati * For crossbow, port id is same as pci function. 1570a20de44SKrishna Gudipati */ 1580a20de44SKrishna Gudipati ioc->port_id = bfa_ioc_pcifn(ioc); 159*a36c61f9SKrishna Gudipati 1600a20de44SKrishna Gudipati bfa_trc(ioc, ioc->port_id); 1610a20de44SKrishna Gudipati } 1620a20de44SKrishna Gudipati 1630a20de44SKrishna Gudipati /** 1640a20de44SKrishna Gudipati * Set interrupt mode for a function: INTX or MSIX 1650a20de44SKrishna Gudipati */ 1660a20de44SKrishna Gudipati static void 1670a20de44SKrishna Gudipati bfa_ioc_cb_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix) 1680a20de44SKrishna Gudipati { 1690a20de44SKrishna Gudipati } 1700a20de44SKrishna Gudipati 1710a20de44SKrishna Gudipati /** 1720a20de44SKrishna Gudipati * Cleanup hw semaphore and usecnt registers 1730a20de44SKrishna Gudipati */ 1740a20de44SKrishna Gudipati static void 1750a20de44SKrishna Gudipati bfa_ioc_cb_ownership_reset(struct bfa_ioc_s *ioc) 1760a20de44SKrishna Gudipati { 1770a20de44SKrishna Gudipati 1780a20de44SKrishna Gudipati /* 1790a20de44SKrishna Gudipati * Read the hw sem reg to make sure that it is locked 1800a20de44SKrishna Gudipati * before we clear it. If it is not locked, writing 1 1810a20de44SKrishna Gudipati * will lock it instead of clearing it. 1820a20de44SKrishna Gudipati */ 1830a20de44SKrishna Gudipati bfa_reg_read(ioc->ioc_regs.ioc_sem_reg); 1840a20de44SKrishna Gudipati bfa_ioc_hw_sem_release(ioc); 1850a20de44SKrishna Gudipati } 186*a36c61f9SKrishna Gudipati 187*a36c61f9SKrishna Gudipati 188*a36c61f9SKrishna Gudipati 189*a36c61f9SKrishna Gudipati bfa_status_t 190*a36c61f9SKrishna Gudipati bfa_ioc_cb_pll_init(bfa_os_addr_t rb, bfa_boolean_t fcmode) 191*a36c61f9SKrishna Gudipati { 192*a36c61f9SKrishna Gudipati u32 pll_sclk, pll_fclk; 193*a36c61f9SKrishna Gudipati 194*a36c61f9SKrishna Gudipati pll_sclk = __APP_PLL_212_ENABLE | __APP_PLL_212_LRESETN | 195*a36c61f9SKrishna Gudipati __APP_PLL_212_P0_1(3U) | 196*a36c61f9SKrishna Gudipati __APP_PLL_212_JITLMT0_1(3U) | 197*a36c61f9SKrishna Gudipati __APP_PLL_212_CNTLMT0_1(3U); 198*a36c61f9SKrishna Gudipati pll_fclk = __APP_PLL_400_ENABLE | __APP_PLL_400_LRESETN | 199*a36c61f9SKrishna Gudipati __APP_PLL_400_RSEL200500 | __APP_PLL_400_P0_1(3U) | 200*a36c61f9SKrishna Gudipati __APP_PLL_400_JITLMT0_1(3U) | 201*a36c61f9SKrishna Gudipati __APP_PLL_400_CNTLMT0_1(3U); 202*a36c61f9SKrishna Gudipati bfa_reg_write((rb + BFA_IOC0_STATE_REG), BFI_IOC_UNINIT); 203*a36c61f9SKrishna Gudipati bfa_reg_write((rb + BFA_IOC1_STATE_REG), BFI_IOC_UNINIT); 204*a36c61f9SKrishna Gudipati bfa_reg_write((rb + HOSTFN0_INT_MSK), 0xffffffffU); 205*a36c61f9SKrishna Gudipati bfa_reg_write((rb + HOSTFN1_INT_MSK), 0xffffffffU); 206*a36c61f9SKrishna Gudipati bfa_reg_write((rb + HOSTFN0_INT_STATUS), 0xffffffffU); 207*a36c61f9SKrishna Gudipati bfa_reg_write((rb + HOSTFN1_INT_STATUS), 0xffffffffU); 208*a36c61f9SKrishna Gudipati bfa_reg_write((rb + HOSTFN0_INT_MSK), 0xffffffffU); 209*a36c61f9SKrishna Gudipati bfa_reg_write((rb + HOSTFN1_INT_MSK), 0xffffffffU); 210*a36c61f9SKrishna Gudipati bfa_reg_write(rb + APP_PLL_212_CTL_REG, 211*a36c61f9SKrishna Gudipati __APP_PLL_212_LOGIC_SOFT_RESET); 212*a36c61f9SKrishna Gudipati bfa_reg_write(rb + APP_PLL_212_CTL_REG, 213*a36c61f9SKrishna Gudipati __APP_PLL_212_BYPASS | 214*a36c61f9SKrishna Gudipati __APP_PLL_212_LOGIC_SOFT_RESET); 215*a36c61f9SKrishna Gudipati bfa_reg_write(rb + APP_PLL_400_CTL_REG, 216*a36c61f9SKrishna Gudipati __APP_PLL_400_LOGIC_SOFT_RESET); 217*a36c61f9SKrishna Gudipati bfa_reg_write(rb + APP_PLL_400_CTL_REG, 218*a36c61f9SKrishna Gudipati __APP_PLL_400_BYPASS | 219*a36c61f9SKrishna Gudipati __APP_PLL_400_LOGIC_SOFT_RESET); 220*a36c61f9SKrishna Gudipati bfa_os_udelay(2); 221*a36c61f9SKrishna Gudipati bfa_reg_write(rb + APP_PLL_212_CTL_REG, 222*a36c61f9SKrishna Gudipati __APP_PLL_212_LOGIC_SOFT_RESET); 223*a36c61f9SKrishna Gudipati bfa_reg_write(rb + APP_PLL_400_CTL_REG, 224*a36c61f9SKrishna Gudipati __APP_PLL_400_LOGIC_SOFT_RESET); 225*a36c61f9SKrishna Gudipati bfa_reg_write(rb + APP_PLL_212_CTL_REG, 226*a36c61f9SKrishna Gudipati pll_sclk | __APP_PLL_212_LOGIC_SOFT_RESET); 227*a36c61f9SKrishna Gudipati bfa_reg_write(rb + APP_PLL_400_CTL_REG, 228*a36c61f9SKrishna Gudipati pll_fclk | __APP_PLL_400_LOGIC_SOFT_RESET); 229*a36c61f9SKrishna Gudipati bfa_os_udelay(2000); 230*a36c61f9SKrishna Gudipati bfa_reg_write((rb + HOSTFN0_INT_STATUS), 0xffffffffU); 231*a36c61f9SKrishna Gudipati bfa_reg_write((rb + HOSTFN1_INT_STATUS), 0xffffffffU); 232*a36c61f9SKrishna Gudipati bfa_reg_write((rb + APP_PLL_212_CTL_REG), pll_sclk); 233*a36c61f9SKrishna Gudipati bfa_reg_write((rb + APP_PLL_400_CTL_REG), pll_fclk); 234*a36c61f9SKrishna Gudipati 235*a36c61f9SKrishna Gudipati return BFA_STATUS_OK; 236*a36c61f9SKrishna Gudipati } 237