xref: /linux/drivers/scsi/bfa/bfa_ioc_cb.c (revision a36c61f9)
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