eb9fbcf598148efba69af3ff2db5192dcd7b1805
[dpdk.git] / drivers / crypto / octeontx / otx_cryptodev_hw_access.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2018 Cavium, Inc
3  */
4 #include <string.h>
5
6 #include <rte_branch_prediction.h>
7 #include <rte_common.h>
8
9 #include "otx_cryptodev_hw_access.h"
10 #include "otx_cryptodev_mbox.h"
11
12 #include "cpt_pmd_logs.h"
13 #include "cpt_hw_types.h"
14
15 /*
16  * VF HAL functions
17  * Access its own BAR0/4 registers by passing VF number as 0.
18  * OS/PCI maps them accordingly.
19  */
20
21 static int
22 otx_cpt_vf_init(struct cpt_vf *cptvf)
23 {
24         int ret = 0;
25
26         /* Check ready with PF */
27         /* Gets chip ID / device Id from PF if ready */
28         ret = otx_cpt_check_pf_ready(cptvf);
29         if (ret) {
30                 CPT_LOG_ERR("%s: PF not responding to READY msg",
31                                 cptvf->dev_name);
32                 ret = -EBUSY;
33                 goto exit;
34         }
35
36         CPT_LOG_DP_DEBUG("%s: %s done", cptvf->dev_name, __func__);
37
38 exit:
39         return ret;
40 }
41
42 /*
43  * Read Interrupt status of the VF
44  *
45  * @param   cptvf       cptvf structure
46  */
47 static uint64_t
48 otx_cpt_read_vf_misc_intr_status(struct cpt_vf *cptvf)
49 {
50         return CPT_READ_CSR(CPT_CSR_REG_BASE(cptvf), CPTX_VQX_MISC_INT(0, 0));
51 }
52
53 /*
54  * Clear mailbox interrupt of the VF
55  *
56  * @param   cptvf       cptvf structure
57  */
58 static void
59 otx_cpt_clear_mbox_intr(struct cpt_vf *cptvf)
60 {
61         cptx_vqx_misc_int_t vqx_misc_int;
62
63         vqx_misc_int.u = CPT_READ_CSR(CPT_CSR_REG_BASE(cptvf),
64                                       CPTX_VQX_MISC_INT(0, 0));
65         /* W1C for the VF */
66         vqx_misc_int.s.mbox = 1;
67         CPT_WRITE_CSR(CPT_CSR_REG_BASE(cptvf),
68                       CPTX_VQX_MISC_INT(0, 0), vqx_misc_int.u);
69 }
70
71 /*
72  * Clear instruction NCB read error interrupt of the VF
73  *
74  * @param   cptvf       cptvf structure
75  */
76 static void
77 otx_cpt_clear_irde_intr(struct cpt_vf *cptvf)
78 {
79         cptx_vqx_misc_int_t vqx_misc_int;
80
81         vqx_misc_int.u = CPT_READ_CSR(CPT_CSR_REG_BASE(cptvf),
82                                       CPTX_VQX_MISC_INT(0, 0));
83         /* W1C for the VF */
84         vqx_misc_int.s.irde = 1;
85         CPT_WRITE_CSR(CPT_CSR_REG_BASE(cptvf),
86                       CPTX_VQX_MISC_INT(0, 0), vqx_misc_int.u);
87 }
88
89 /*
90  * Clear NCB result write response error interrupt of the VF
91  *
92  * @param   cptvf       cptvf structure
93  */
94 static void
95 otx_cpt_clear_nwrp_intr(struct cpt_vf *cptvf)
96 {
97         cptx_vqx_misc_int_t vqx_misc_int;
98
99         vqx_misc_int.u = CPT_READ_CSR(CPT_CSR_REG_BASE(cptvf),
100                                       CPTX_VQX_MISC_INT(0, 0));
101         /* W1C for the VF */
102         vqx_misc_int.s.nwrp = 1;
103         CPT_WRITE_CSR(CPT_CSR_REG_BASE(cptvf),
104                       CPTX_VQX_MISC_INT(0, 0), vqx_misc_int.u);
105 }
106
107 /*
108  * Clear swerr interrupt of the VF
109  *
110  * @param   cptvf       cptvf structure
111  */
112 static void
113 otx_cpt_clear_swerr_intr(struct cpt_vf *cptvf)
114 {
115         cptx_vqx_misc_int_t vqx_misc_int;
116
117         vqx_misc_int.u = CPT_READ_CSR(CPT_CSR_REG_BASE(cptvf),
118                                       CPTX_VQX_MISC_INT(0, 0));
119         /* W1C for the VF */
120         vqx_misc_int.s.swerr = 1;
121         CPT_WRITE_CSR(CPT_CSR_REG_BASE(cptvf),
122                       CPTX_VQX_MISC_INT(0, 0), vqx_misc_int.u);
123 }
124
125 /*
126  * Clear hwerr interrupt of the VF
127  *
128  * @param   cptvf       cptvf structure
129  */
130 static void
131 otx_cpt_clear_hwerr_intr(struct cpt_vf *cptvf)
132 {
133         cptx_vqx_misc_int_t vqx_misc_int;
134
135         vqx_misc_int.u = CPT_READ_CSR(CPT_CSR_REG_BASE(cptvf),
136                                       CPTX_VQX_MISC_INT(0, 0));
137         /* W1C for the VF */
138         vqx_misc_int.s.hwerr = 1;
139         CPT_WRITE_CSR(CPT_CSR_REG_BASE(cptvf),
140                       CPTX_VQX_MISC_INT(0, 0), vqx_misc_int.u);
141 }
142
143 /*
144  * Clear translation fault interrupt of the VF
145  *
146  * @param   cptvf       cptvf structure
147  */
148 static void
149 otx_cpt_clear_fault_intr(struct cpt_vf *cptvf)
150 {
151         cptx_vqx_misc_int_t vqx_misc_int;
152
153         vqx_misc_int.u = CPT_READ_CSR(CPT_CSR_REG_BASE(cptvf),
154                                 CPTX_VQX_MISC_INT(0, 0));
155         /* W1C for the VF */
156         vqx_misc_int.s.fault = 1;
157         CPT_WRITE_CSR(CPT_CSR_REG_BASE(cptvf),
158                 CPTX_VQX_MISC_INT(0, 0), vqx_misc_int.u);
159 }
160
161 /*
162  * Clear doorbell overflow interrupt of the VF
163  *
164  * @param   cptvf       cptvf structure
165  */
166 static void
167 otx_cpt_clear_dovf_intr(struct cpt_vf *cptvf)
168 {
169         cptx_vqx_misc_int_t vqx_misc_int;
170
171         vqx_misc_int.u = CPT_READ_CSR(CPT_CSR_REG_BASE(cptvf),
172                                       CPTX_VQX_MISC_INT(0, 0));
173         /* W1C for the VF */
174         vqx_misc_int.s.dovf = 1;
175         CPT_WRITE_CSR(CPT_CSR_REG_BASE(cptvf),
176                       CPTX_VQX_MISC_INT(0, 0), vqx_misc_int.u);
177 }
178
179 void
180 otx_cpt_poll_misc(struct cpt_vf *cptvf)
181 {
182         uint64_t intr;
183
184         intr = otx_cpt_read_vf_misc_intr_status(cptvf);
185
186         if (!intr)
187                 return;
188
189         /* Check for MISC interrupt types */
190         if (likely(intr & CPT_VF_INTR_MBOX_MASK)) {
191                 CPT_LOG_DP_DEBUG("%s: Mailbox interrupt 0x%lx on CPT VF %d",
192                         cptvf->dev_name, (unsigned int long)intr, cptvf->vfid);
193                 otx_cpt_handle_mbox_intr(cptvf);
194                 otx_cpt_clear_mbox_intr(cptvf);
195         } else if (unlikely(intr & CPT_VF_INTR_IRDE_MASK)) {
196                 otx_cpt_clear_irde_intr(cptvf);
197                 CPT_LOG_DP_DEBUG("%s: Instruction NCB read error interrupt "
198                                 "0x%lx on CPT VF %d", cptvf->dev_name,
199                                 (unsigned int long)intr, cptvf->vfid);
200         } else if (unlikely(intr & CPT_VF_INTR_NWRP_MASK)) {
201                 otx_cpt_clear_nwrp_intr(cptvf);
202                 CPT_LOG_DP_DEBUG("%s: NCB response write error interrupt 0x%lx"
203                                 " on CPT VF %d", cptvf->dev_name,
204                                 (unsigned int long)intr, cptvf->vfid);
205         } else if (unlikely(intr & CPT_VF_INTR_SWERR_MASK)) {
206                 otx_cpt_clear_swerr_intr(cptvf);
207                 CPT_LOG_DP_DEBUG("%s: Software error interrupt 0x%lx on CPT VF "
208                                 "%d", cptvf->dev_name, (unsigned int long)intr,
209                                 cptvf->vfid);
210         } else if (unlikely(intr & CPT_VF_INTR_HWERR_MASK)) {
211                 otx_cpt_clear_hwerr_intr(cptvf);
212                 CPT_LOG_DP_DEBUG("%s: Hardware error interrupt 0x%lx on CPT VF "
213                                 "%d", cptvf->dev_name, (unsigned int long)intr,
214                                 cptvf->vfid);
215         } else if (unlikely(intr & CPT_VF_INTR_FAULT_MASK)) {
216                 otx_cpt_clear_fault_intr(cptvf);
217                 CPT_LOG_DP_DEBUG("%s: Translation fault interrupt 0x%lx on CPT VF "
218                                 "%d", cptvf->dev_name, (unsigned int long)intr,
219                                 cptvf->vfid);
220         } else if (unlikely(intr & CPT_VF_INTR_DOVF_MASK)) {
221                 otx_cpt_clear_dovf_intr(cptvf);
222                 CPT_LOG_DP_DEBUG("%s: Doorbell overflow interrupt 0x%lx on CPT VF "
223                                 "%d", cptvf->dev_name, (unsigned int long)intr,
224                                 cptvf->vfid);
225         } else
226                 CPT_LOG_DP_ERR("%s: Unhandled interrupt 0x%lx in CPT VF %d",
227                                 cptvf->dev_name, (unsigned int long)intr,
228                                 cptvf->vfid);
229 }
230
231 int
232 otx_cpt_hw_init(struct cpt_vf *cptvf, void *pdev, void *reg_base, char *name)
233 {
234         memset(cptvf, 0, sizeof(struct cpt_vf));
235
236         /* Bar0 base address */
237         cptvf->reg_base = reg_base;
238         strncpy(cptvf->dev_name, name, 32);
239
240         cptvf->pdev = pdev;
241
242         /* To clear if there are any pending mbox msgs */
243         otx_cpt_poll_misc(cptvf);
244
245         if (otx_cpt_vf_init(cptvf)) {
246                 CPT_LOG_ERR("Failed to initialize CPT VF device");
247                 return -1;
248         }
249
250         return 0;
251 }
252
253 int
254 otx_cpt_deinit_device(void *dev)
255 {
256         struct cpt_vf *cptvf = (struct cpt_vf *)dev;
257
258         /* Do misc work one last time */
259         otx_cpt_poll_misc(cptvf);
260
261         return 0;
262 }