1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Copyright (c) 2005-2014 Brocade Communications Systems, Inc.
4*4882a593Smuzhiyun * Copyright (c) 2014- QLogic Corporation.
5*4882a593Smuzhiyun * All rights reserved
6*4882a593Smuzhiyun * www.qlogic.com
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * Linux driver for QLogic BR-series Fibre Channel Host Bus Adapter.
9*4882a593Smuzhiyun */
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun #include "bfad_drv.h"
12*4882a593Smuzhiyun #include "bfa_modules.h"
13*4882a593Smuzhiyun #include "bfi_reg.h"
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun void
bfa_hwcb_reginit(struct bfa_s * bfa)16*4882a593Smuzhiyun bfa_hwcb_reginit(struct bfa_s *bfa)
17*4882a593Smuzhiyun {
18*4882a593Smuzhiyun struct bfa_iocfc_regs_s *bfa_regs = &bfa->iocfc.bfa_regs;
19*4882a593Smuzhiyun void __iomem *kva = bfa_ioc_bar0(&bfa->ioc);
20*4882a593Smuzhiyun int fn = bfa_ioc_pcifn(&bfa->ioc);
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun if (fn == 0) {
23*4882a593Smuzhiyun bfa_regs->intr_status = (kva + HOSTFN0_INT_STATUS);
24*4882a593Smuzhiyun bfa_regs->intr_mask = (kva + HOSTFN0_INT_MSK);
25*4882a593Smuzhiyun } else {
26*4882a593Smuzhiyun bfa_regs->intr_status = (kva + HOSTFN1_INT_STATUS);
27*4882a593Smuzhiyun bfa_regs->intr_mask = (kva + HOSTFN1_INT_MSK);
28*4882a593Smuzhiyun }
29*4882a593Smuzhiyun }
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun static void
bfa_hwcb_reqq_ack_msix(struct bfa_s * bfa,int reqq)32*4882a593Smuzhiyun bfa_hwcb_reqq_ack_msix(struct bfa_s *bfa, int reqq)
33*4882a593Smuzhiyun {
34*4882a593Smuzhiyun writel(__HFN_INT_CPE_Q0 << CPE_Q_NUM(bfa_ioc_pcifn(&bfa->ioc), reqq),
35*4882a593Smuzhiyun bfa->iocfc.bfa_regs.intr_status);
36*4882a593Smuzhiyun }
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun /*
39*4882a593Smuzhiyun * Actions to respond RME Interrupt for Crossbow ASIC:
40*4882a593Smuzhiyun * - Write 1 to Interrupt Status register
41*4882a593Smuzhiyun * INTX - done in bfa_intx()
42*4882a593Smuzhiyun * MSIX - done in bfa_hwcb_rspq_ack_msix()
43*4882a593Smuzhiyun * - Update CI (only if new CI)
44*4882a593Smuzhiyun */
45*4882a593Smuzhiyun static void
bfa_hwcb_rspq_ack_msix(struct bfa_s * bfa,int rspq,u32 ci)46*4882a593Smuzhiyun bfa_hwcb_rspq_ack_msix(struct bfa_s *bfa, int rspq, u32 ci)
47*4882a593Smuzhiyun {
48*4882a593Smuzhiyun writel(__HFN_INT_RME_Q0 << RME_Q_NUM(bfa_ioc_pcifn(&bfa->ioc), rspq),
49*4882a593Smuzhiyun bfa->iocfc.bfa_regs.intr_status);
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun if (bfa_rspq_ci(bfa, rspq) == ci)
52*4882a593Smuzhiyun return;
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun bfa_rspq_ci(bfa, rspq) = ci;
55*4882a593Smuzhiyun writel(ci, bfa->iocfc.bfa_regs.rme_q_ci[rspq]);
56*4882a593Smuzhiyun }
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun void
bfa_hwcb_rspq_ack(struct bfa_s * bfa,int rspq,u32 ci)59*4882a593Smuzhiyun bfa_hwcb_rspq_ack(struct bfa_s *bfa, int rspq, u32 ci)
60*4882a593Smuzhiyun {
61*4882a593Smuzhiyun if (bfa_rspq_ci(bfa, rspq) == ci)
62*4882a593Smuzhiyun return;
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun bfa_rspq_ci(bfa, rspq) = ci;
65*4882a593Smuzhiyun writel(ci, bfa->iocfc.bfa_regs.rme_q_ci[rspq]);
66*4882a593Smuzhiyun }
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun void
bfa_hwcb_msix_getvecs(struct bfa_s * bfa,u32 * msix_vecs_bmap,u32 * num_vecs,u32 * max_vec_bit)69*4882a593Smuzhiyun bfa_hwcb_msix_getvecs(struct bfa_s *bfa, u32 *msix_vecs_bmap,
70*4882a593Smuzhiyun u32 *num_vecs, u32 *max_vec_bit)
71*4882a593Smuzhiyun {
72*4882a593Smuzhiyun #define __HFN_NUMINTS 13
73*4882a593Smuzhiyun if (bfa_ioc_pcifn(&bfa->ioc) == 0) {
74*4882a593Smuzhiyun *msix_vecs_bmap = (__HFN_INT_CPE_Q0 | __HFN_INT_CPE_Q1 |
75*4882a593Smuzhiyun __HFN_INT_CPE_Q2 | __HFN_INT_CPE_Q3 |
76*4882a593Smuzhiyun __HFN_INT_RME_Q0 | __HFN_INT_RME_Q1 |
77*4882a593Smuzhiyun __HFN_INT_RME_Q2 | __HFN_INT_RME_Q3 |
78*4882a593Smuzhiyun __HFN_INT_MBOX_LPU0);
79*4882a593Smuzhiyun *max_vec_bit = __HFN_INT_MBOX_LPU0;
80*4882a593Smuzhiyun } else {
81*4882a593Smuzhiyun *msix_vecs_bmap = (__HFN_INT_CPE_Q4 | __HFN_INT_CPE_Q5 |
82*4882a593Smuzhiyun __HFN_INT_CPE_Q6 | __HFN_INT_CPE_Q7 |
83*4882a593Smuzhiyun __HFN_INT_RME_Q4 | __HFN_INT_RME_Q5 |
84*4882a593Smuzhiyun __HFN_INT_RME_Q6 | __HFN_INT_RME_Q7 |
85*4882a593Smuzhiyun __HFN_INT_MBOX_LPU1);
86*4882a593Smuzhiyun *max_vec_bit = __HFN_INT_MBOX_LPU1;
87*4882a593Smuzhiyun }
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun *msix_vecs_bmap |= (__HFN_INT_ERR_EMC | __HFN_INT_ERR_LPU0 |
90*4882a593Smuzhiyun __HFN_INT_ERR_LPU1 | __HFN_INT_ERR_PSS);
91*4882a593Smuzhiyun *num_vecs = __HFN_NUMINTS;
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun /*
95*4882a593Smuzhiyun * Dummy interrupt handler for handling spurious interrupts.
96*4882a593Smuzhiyun */
97*4882a593Smuzhiyun static void
bfa_hwcb_msix_dummy(struct bfa_s * bfa,int vec)98*4882a593Smuzhiyun bfa_hwcb_msix_dummy(struct bfa_s *bfa, int vec)
99*4882a593Smuzhiyun {
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun /*
103*4882a593Smuzhiyun * No special setup required for crossbow -- vector assignments are implicit.
104*4882a593Smuzhiyun */
105*4882a593Smuzhiyun void
bfa_hwcb_msix_init(struct bfa_s * bfa,int nvecs)106*4882a593Smuzhiyun bfa_hwcb_msix_init(struct bfa_s *bfa, int nvecs)
107*4882a593Smuzhiyun {
108*4882a593Smuzhiyun WARN_ON((nvecs != 1) && (nvecs != __HFN_NUMINTS));
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun bfa->msix.nvecs = nvecs;
111*4882a593Smuzhiyun bfa_hwcb_msix_uninstall(bfa);
112*4882a593Smuzhiyun }
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun void
bfa_hwcb_msix_ctrl_install(struct bfa_s * bfa)115*4882a593Smuzhiyun bfa_hwcb_msix_ctrl_install(struct bfa_s *bfa)
116*4882a593Smuzhiyun {
117*4882a593Smuzhiyun int i;
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun if (bfa->msix.nvecs == 0)
120*4882a593Smuzhiyun return;
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun if (bfa->msix.nvecs == 1) {
123*4882a593Smuzhiyun for (i = BFI_MSIX_CPE_QMIN_CB; i < BFI_MSIX_CB_MAX; i++)
124*4882a593Smuzhiyun bfa->msix.handler[i] = bfa_msix_all;
125*4882a593Smuzhiyun return;
126*4882a593Smuzhiyun }
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun for (i = BFI_MSIX_RME_QMAX_CB+1; i < BFI_MSIX_CB_MAX; i++)
129*4882a593Smuzhiyun bfa->msix.handler[i] = bfa_msix_lpu_err;
130*4882a593Smuzhiyun }
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun void
bfa_hwcb_msix_queue_install(struct bfa_s * bfa)133*4882a593Smuzhiyun bfa_hwcb_msix_queue_install(struct bfa_s *bfa)
134*4882a593Smuzhiyun {
135*4882a593Smuzhiyun int i;
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun if (bfa->msix.nvecs == 0)
138*4882a593Smuzhiyun return;
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun if (bfa->msix.nvecs == 1) {
141*4882a593Smuzhiyun for (i = BFI_MSIX_CPE_QMIN_CB; i <= BFI_MSIX_RME_QMAX_CB; i++)
142*4882a593Smuzhiyun bfa->msix.handler[i] = bfa_msix_all;
143*4882a593Smuzhiyun return;
144*4882a593Smuzhiyun }
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun for (i = BFI_MSIX_CPE_QMIN_CB; i <= BFI_MSIX_CPE_QMAX_CB; i++)
147*4882a593Smuzhiyun bfa->msix.handler[i] = bfa_msix_reqq;
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun for (i = BFI_MSIX_RME_QMIN_CB; i <= BFI_MSIX_RME_QMAX_CB; i++)
150*4882a593Smuzhiyun bfa->msix.handler[i] = bfa_msix_rspq;
151*4882a593Smuzhiyun }
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun void
bfa_hwcb_msix_uninstall(struct bfa_s * bfa)154*4882a593Smuzhiyun bfa_hwcb_msix_uninstall(struct bfa_s *bfa)
155*4882a593Smuzhiyun {
156*4882a593Smuzhiyun int i;
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun for (i = 0; i < BFI_MSIX_CB_MAX; i++)
159*4882a593Smuzhiyun bfa->msix.handler[i] = bfa_hwcb_msix_dummy;
160*4882a593Smuzhiyun }
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun /*
163*4882a593Smuzhiyun * No special enable/disable -- vector assignments are implicit.
164*4882a593Smuzhiyun */
165*4882a593Smuzhiyun void
bfa_hwcb_isr_mode_set(struct bfa_s * bfa,bfa_boolean_t msix)166*4882a593Smuzhiyun bfa_hwcb_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix)
167*4882a593Smuzhiyun {
168*4882a593Smuzhiyun if (msix) {
169*4882a593Smuzhiyun bfa->iocfc.hwif.hw_reqq_ack = bfa_hwcb_reqq_ack_msix;
170*4882a593Smuzhiyun bfa->iocfc.hwif.hw_rspq_ack = bfa_hwcb_rspq_ack_msix;
171*4882a593Smuzhiyun } else {
172*4882a593Smuzhiyun bfa->iocfc.hwif.hw_reqq_ack = NULL;
173*4882a593Smuzhiyun bfa->iocfc.hwif.hw_rspq_ack = bfa_hwcb_rspq_ack;
174*4882a593Smuzhiyun }
175*4882a593Smuzhiyun }
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun void
bfa_hwcb_msix_get_rme_range(struct bfa_s * bfa,u32 * start,u32 * end)178*4882a593Smuzhiyun bfa_hwcb_msix_get_rme_range(struct bfa_s *bfa, u32 *start, u32 *end)
179*4882a593Smuzhiyun {
180*4882a593Smuzhiyun *start = BFI_MSIX_RME_QMIN_CB;
181*4882a593Smuzhiyun *end = BFI_MSIX_RME_QMAX_CB;
182*4882a593Smuzhiyun }
183