crypto/cnxk: move IPsec SA creation to common
[dpdk.git] / drivers / common / cnxk / roc_bphy_cgx.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2021 Marvell.
3  */
4
5 #include <pthread.h>
6
7 #include "roc_api.h"
8 #include "roc_priv.h"
9
10 #define CGX_CMRX_CONFIG                0x00
11 #define CGX_CMRX_CONFIG_DATA_PKT_RX_EN BIT_ULL(54)
12 #define CGX_CMRX_CONFIG_DATA_PKT_TX_EN BIT_ULL(53)
13 #define CGX_CMRX_INT                   0x40
14 #define CGX_CMRX_INT_OVERFLW           BIT_ULL(1)
15 /*
16  * CN10K stores number of lmacs in 4 bit filed
17  * in contrary to CN9K which uses only 3 bits.
18  *
19  * In theory masks should differ yet on CN9K
20  * bits beyond specified range contain zeros.
21  *
22  * Hence common longer mask may be used.
23  */
24 #define CGX_CMRX_RX_LMACS                     0x128
25 #define CGX_CMRX_RX_LMACS_LMACS               GENMASK_ULL(3, 0)
26 #define CGX_CMRX_SCRATCH0                     0x1050
27 #define CGX_CMRX_SCRATCH1                     0x1058
28 #define CGX_MTI_MAC100X_COMMAND_CONFIG        0x8010
29 #define CGX_MTI_MAC100X_COMMAND_CONFIG_RX_ENA BIT_ULL(1)
30 #define CGX_MTI_MAC100X_COMMAND_CONFIG_TX_ENA BIT_ULL(0)
31
32 static uint64_t
33 roc_bphy_cgx_read(struct roc_bphy_cgx *roc_cgx, uint64_t lmac, uint64_t offset)
34 {
35         int shift = roc_model_is_cn10k() ? 20 : 18;
36         uint64_t base = (uint64_t)roc_cgx->bar0_va;
37
38         return plt_read64(base + (lmac << shift) + offset);
39 }
40
41 static void
42 roc_bphy_cgx_write(struct roc_bphy_cgx *roc_cgx, uint64_t lmac, uint64_t offset,
43                    uint64_t value)
44 {
45         int shift = roc_model_is_cn10k() ? 20 : 18;
46         uint64_t base = (uint64_t)roc_cgx->bar0_va;
47
48         plt_write64(value, base + (lmac << shift) + offset);
49 }
50
51 static void
52 roc_bphy_cgx_ack(struct roc_bphy_cgx *roc_cgx, unsigned int lmac,
53                  uint64_t *scr0)
54 {
55         uint64_t val;
56
57         /* clear interrupt */
58         val = roc_bphy_cgx_read(roc_cgx, lmac, CGX_CMRX_INT);
59         val |= FIELD_PREP(CGX_CMRX_INT_OVERFLW, 1);
60         roc_bphy_cgx_write(roc_cgx, lmac, CGX_CMRX_INT, val);
61
62         /* ack fw response */
63         *scr0 &= ~SCR0_ETH_EVT_STS_S_ACK;
64         roc_bphy_cgx_write(roc_cgx, lmac, CGX_CMRX_SCRATCH0, *scr0);
65 }
66
67 static int
68 roc_bphy_cgx_wait_for_ownership(struct roc_bphy_cgx *roc_cgx, unsigned int lmac,
69                                 uint64_t *scr0)
70 {
71         int tries = 5000;
72         uint64_t scr1;
73
74         do {
75                 *scr0 = roc_bphy_cgx_read(roc_cgx, lmac, CGX_CMRX_SCRATCH0);
76                 scr1 = roc_bphy_cgx_read(roc_cgx, lmac, CGX_CMRX_SCRATCH1);
77
78                 if (FIELD_GET(SCR1_OWN_STATUS, scr1) == ETH_OWN_NON_SECURE_SW &&
79                     FIELD_GET(SCR0_ETH_EVT_STS_S_ACK, *scr0) == 0)
80                         break;
81
82                 /* clear async events if any */
83                 if (FIELD_GET(SCR0_ETH_EVT_STS_S_EVT_TYPE, *scr0) ==
84                     ETH_EVT_ASYNC &&
85                     FIELD_GET(SCR0_ETH_EVT_STS_S_ACK, *scr0))
86                         roc_bphy_cgx_ack(roc_cgx, lmac, scr0);
87
88                 plt_delay_ms(1);
89         } while (--tries);
90
91         return tries ? 0 : -ETIMEDOUT;
92 }
93
94 static int
95 roc_bphy_cgx_wait_for_ack(struct roc_bphy_cgx *roc_cgx, unsigned int lmac,
96                           uint64_t *scr0)
97 {
98         int tries = 5000;
99         uint64_t scr1;
100
101         do {
102                 *scr0 = roc_bphy_cgx_read(roc_cgx, lmac, CGX_CMRX_SCRATCH0);
103                 scr1 = roc_bphy_cgx_read(roc_cgx, lmac, CGX_CMRX_SCRATCH1);
104
105                 if (FIELD_GET(SCR1_OWN_STATUS, scr1) == ETH_OWN_NON_SECURE_SW &&
106                     FIELD_GET(SCR0_ETH_EVT_STS_S_ACK, *scr0))
107                         break;
108
109                 plt_delay_ms(1);
110         } while (--tries);
111
112         return tries ? 0 : -ETIMEDOUT;
113 }
114
115 static int
116 roc_bphy_cgx_intf_req(struct roc_bphy_cgx *roc_cgx, unsigned int lmac,
117                       uint64_t scr1, uint64_t *scr0)
118 {
119         uint8_t cmd_id = FIELD_GET(SCR1_ETH_CMD_ID, scr1);
120         int ret;
121
122         pthread_mutex_lock(&roc_cgx->lock);
123
124         /* wait for ownership */
125         ret = roc_bphy_cgx_wait_for_ownership(roc_cgx, lmac, scr0);
126         if (ret) {
127                 plt_err("timed out waiting for ownership");
128                 goto out;
129         }
130
131         /* write command */
132         scr1 |= FIELD_PREP(SCR1_OWN_STATUS, ETH_OWN_FIRMWARE);
133         roc_bphy_cgx_write(roc_cgx, lmac, CGX_CMRX_SCRATCH1, scr1);
134
135         /* wait for command ack */
136         ret = roc_bphy_cgx_wait_for_ack(roc_cgx, lmac, scr0);
137         if (ret) {
138                 plt_err("timed out waiting for response");
139                 goto out;
140         }
141
142         if (cmd_id == ETH_CMD_INTF_SHUTDOWN)
143                 goto out;
144
145         if (FIELD_GET(SCR0_ETH_EVT_STS_S_EVT_TYPE, *scr0) != ETH_EVT_CMD_RESP) {
146                 plt_err("received async event instead of cmd resp event");
147                 ret = -EIO;
148                 goto out;
149         }
150
151         if (FIELD_GET(SCR0_ETH_EVT_STS_S_ID, *scr0) != cmd_id) {
152                 plt_err("received resp for cmd %d expected for cmd %d",
153                         (int)FIELD_GET(SCR0_ETH_EVT_STS_S_ID, *scr0), cmd_id);
154                 ret = -EIO;
155                 goto out;
156         }
157
158         if (FIELD_GET(SCR0_ETH_EVT_STS_S_STAT, *scr0) != ETH_STAT_SUCCESS) {
159                 plt_err("cmd %d failed on cgx%u lmac%u with errcode %d", cmd_id,
160                         roc_cgx->id, lmac,
161                         (int)FIELD_GET(SCR0_ETH_LNK_STS_S_ERR_TYPE, *scr0));
162                 ret = -EIO;
163         }
164
165 out:
166         roc_bphy_cgx_ack(roc_cgx, lmac, scr0);
167
168         pthread_mutex_unlock(&roc_cgx->lock);
169
170         return ret;
171 }
172
173 static unsigned int
174 roc_bphy_cgx_dev_id(struct roc_bphy_cgx *roc_cgx)
175 {
176         uint64_t cgx_id;
177
178         if (roc_model_is_cnf10kb())
179                 cgx_id = GENMASK_ULL(27, 24);
180         else if (roc_model_is_cn10k())
181                 cgx_id = GENMASK_ULL(26, 24);
182         else
183                 cgx_id = GENMASK_ULL(25, 24);
184
185         return FIELD_GET(cgx_id, roc_cgx->bar0_pa);
186 }
187
188 int
189 roc_bphy_cgx_dev_init(struct roc_bphy_cgx *roc_cgx)
190 {
191         uint64_t val;
192         int ret;
193
194         if (!roc_cgx || !roc_cgx->bar0_va || !roc_cgx->bar0_pa)
195                 return -EINVAL;
196
197         ret = pthread_mutex_init(&roc_cgx->lock, NULL);
198         if (ret)
199                 return ret;
200
201         val = roc_bphy_cgx_read(roc_cgx, 0, CGX_CMRX_RX_LMACS);
202         val = FIELD_GET(CGX_CMRX_RX_LMACS_LMACS, val);
203         if (roc_model_is_cn9k())
204                 val = GENMASK_ULL(val - 1, 0);
205         roc_cgx->lmac_bmap = val;
206         roc_cgx->id = roc_bphy_cgx_dev_id(roc_cgx);
207
208         return 0;
209 }
210
211 int
212 roc_bphy_cgx_dev_fini(struct roc_bphy_cgx *roc_cgx)
213 {
214         if (!roc_cgx)
215                 return -EINVAL;
216
217         pthread_mutex_destroy(&roc_cgx->lock);
218
219         return 0;
220 }
221
222 static bool
223 roc_bphy_cgx_lmac_exists(struct roc_bphy_cgx *roc_cgx, unsigned int lmac)
224 {
225         return (lmac < MAX_LMACS_PER_CGX) &&
226                (roc_cgx->lmac_bmap & BIT_ULL(lmac));
227 }
228
229 static int
230 roc_bphy_cgx_start_stop_rxtx(struct roc_bphy_cgx *roc_cgx, unsigned int lmac,
231                              bool start)
232 {
233         uint64_t val, reg, rx_field, tx_field;
234
235         if (!roc_cgx)
236                 return -EINVAL;
237
238         if (!roc_bphy_cgx_lmac_exists(roc_cgx, lmac))
239                 return -ENODEV;
240
241         if (roc_model_is_cnf10kb()) {
242                 reg = CGX_MTI_MAC100X_COMMAND_CONFIG;
243                 rx_field = CGX_MTI_MAC100X_COMMAND_CONFIG_RX_ENA;
244                 tx_field = CGX_MTI_MAC100X_COMMAND_CONFIG_TX_ENA;
245         } else {
246                 reg = CGX_CMRX_CONFIG;
247                 rx_field = CGX_CMRX_CONFIG_DATA_PKT_RX_EN;
248                 tx_field = CGX_CMRX_CONFIG_DATA_PKT_TX_EN;
249         }
250
251         pthread_mutex_lock(&roc_cgx->lock);
252         val = roc_bphy_cgx_read(roc_cgx, lmac, reg);
253         val &= ~(rx_field | tx_field);
254
255         if (start)
256                 val |= FIELD_PREP(rx_field, 1) | FIELD_PREP(tx_field, 1);
257
258         roc_bphy_cgx_write(roc_cgx, lmac, reg, val);
259         pthread_mutex_unlock(&roc_cgx->lock);
260
261         return 0;
262 }
263
264 static int
265 roc_bphy_cgx_intlbk_ena_dis(struct roc_bphy_cgx *roc_cgx, unsigned int lmac,
266                             bool enable)
267 {
268         uint64_t scr1, scr0;
269
270         if (!roc_cgx)
271                 return -EINVAL;
272
273         if (!roc_bphy_cgx_lmac_exists(roc_cgx, lmac))
274                 return -ENODEV;
275
276         scr1 = FIELD_PREP(SCR1_ETH_CMD_ID, ETH_CMD_INTERNAL_LBK) |
277                FIELD_PREP(SCR1_ETH_CTL_ARGS_ENABLE, enable);
278
279         return roc_bphy_cgx_intf_req(roc_cgx, lmac, scr1, &scr0);
280 }
281
282 static int
283 roc_bphy_cgx_ptp_rx_ena_dis(struct roc_bphy_cgx *roc_cgx, unsigned int lmac,
284                             bool enable)
285 {
286         uint64_t scr1, scr0;
287
288         if (roc_model_is_cn10k())
289                 return -ENOTSUP;
290
291         if (!roc_cgx)
292                 return -EINVAL;
293
294         if (!roc_bphy_cgx_lmac_exists(roc_cgx, lmac))
295                 return -ENODEV;
296
297         scr1 = FIELD_PREP(SCR1_ETH_CMD_ID, ETH_CMD_SET_PTP_MODE) |
298                FIELD_PREP(SCR1_ETH_CTL_ARGS_ENABLE, enable);
299
300         return roc_bphy_cgx_intf_req(roc_cgx, lmac, scr1, &scr0);
301 }
302
303 int
304 roc_bphy_cgx_start_rxtx(struct roc_bphy_cgx *roc_cgx, unsigned int lmac)
305 {
306         return roc_bphy_cgx_start_stop_rxtx(roc_cgx, lmac, true);
307 }
308
309 int
310 roc_bphy_cgx_stop_rxtx(struct roc_bphy_cgx *roc_cgx, unsigned int lmac)
311 {
312         return roc_bphy_cgx_start_stop_rxtx(roc_cgx, lmac, false);
313 }
314
315 int
316 roc_bphy_cgx_set_link_state(struct roc_bphy_cgx *roc_cgx, unsigned int lmac,
317                             bool state)
318 {
319         uint64_t scr1, scr0;
320
321         if (!roc_cgx)
322                 return -EINVAL;
323
324         if (!roc_bphy_cgx_lmac_exists(roc_cgx, lmac))
325                 return -ENODEV;
326
327         scr1 = state ? FIELD_PREP(SCR1_ETH_CMD_ID, ETH_CMD_LINK_BRING_UP) :
328                        FIELD_PREP(SCR1_ETH_CMD_ID, ETH_CMD_LINK_BRING_DOWN);
329
330         return roc_bphy_cgx_intf_req(roc_cgx, lmac, scr1, &scr0);
331 }
332
333 int
334 roc_bphy_cgx_get_linkinfo(struct roc_bphy_cgx *roc_cgx, unsigned int lmac,
335                           struct roc_bphy_cgx_link_info *info)
336 {
337         uint64_t scr1, scr0;
338         int ret;
339
340         if (!roc_cgx)
341                 return -EINVAL;
342
343         if (!roc_bphy_cgx_lmac_exists(roc_cgx, lmac))
344                 return -ENODEV;
345
346         if (!info)
347                 return -EINVAL;
348
349         scr1 = FIELD_PREP(SCR1_ETH_CMD_ID, ETH_CMD_GET_LINK_STS);
350         ret = roc_bphy_cgx_intf_req(roc_cgx, lmac, scr1, &scr0);
351         if (ret)
352                 return ret;
353
354         info->link_up = FIELD_GET(SCR0_ETH_LNK_STS_S_LINK_UP, scr0);
355         info->full_duplex = FIELD_GET(SCR0_ETH_LNK_STS_S_FULL_DUPLEX, scr0);
356         info->speed = FIELD_GET(SCR0_ETH_LNK_STS_S_SPEED, scr0);
357         info->an = FIELD_GET(SCR0_ETH_LNK_STS_S_AN, scr0);
358         info->fec = FIELD_GET(SCR0_ETH_LNK_STS_S_FEC, scr0);
359         info->mode = FIELD_GET(SCR0_ETH_LNK_STS_S_MODE, scr0);
360
361         return 0;
362 }
363
364 int
365 roc_bphy_cgx_set_link_mode(struct roc_bphy_cgx *roc_cgx, unsigned int lmac,
366                            struct roc_bphy_cgx_link_mode *mode)
367 {
368         uint64_t scr1, scr0;
369
370         if (roc_model_is_cn9k() &&
371             (mode->use_portm_idx || mode->portm_idx || mode->mode_group_idx)) {
372                 return -ENOTSUP;
373         }
374
375         if (!roc_cgx)
376                 return -EINVAL;
377
378         if (!roc_bphy_cgx_lmac_exists(roc_cgx, lmac))
379                 return -ENODEV;
380
381         if (!mode)
382                 return -EINVAL;
383
384         scr1 = FIELD_PREP(SCR1_ETH_CMD_ID, ETH_CMD_MODE_CHANGE) |
385                FIELD_PREP(SCR1_ETH_MODE_CHANGE_ARGS_SPEED, mode->speed) |
386                FIELD_PREP(SCR1_ETH_MODE_CHANGE_ARGS_DUPLEX, mode->full_duplex) |
387                FIELD_PREP(SCR1_ETH_MODE_CHANGE_ARGS_AN, mode->an) |
388                FIELD_PREP(SCR1_ETH_MODE_CHANGE_ARGS_USE_PORTM_IDX,
389                           mode->use_portm_idx) |
390                FIELD_PREP(SCR1_ETH_MODE_CHANGE_ARGS_PORTM_IDX,
391                           mode->portm_idx) |
392                FIELD_PREP(SCR1_ETH_MODE_CHANGE_ARGS_MODE_GROUP_IDX,
393                           mode->mode_group_idx) |
394                FIELD_PREP(SCR1_ETH_MODE_CHANGE_ARGS_MODE, BIT_ULL(mode->mode));
395
396         return roc_bphy_cgx_intf_req(roc_cgx, lmac, scr1, &scr0);
397 }
398
399 int
400 roc_bphy_cgx_intlbk_enable(struct roc_bphy_cgx *roc_cgx, unsigned int lmac)
401 {
402         return roc_bphy_cgx_intlbk_ena_dis(roc_cgx, lmac, true);
403 }
404
405 int
406 roc_bphy_cgx_intlbk_disable(struct roc_bphy_cgx *roc_cgx, unsigned int lmac)
407 {
408         return roc_bphy_cgx_intlbk_ena_dis(roc_cgx, lmac, false);
409 }
410
411 int
412 roc_bphy_cgx_ptp_rx_enable(struct roc_bphy_cgx *roc_cgx, unsigned int lmac)
413 {
414         return roc_bphy_cgx_ptp_rx_ena_dis(roc_cgx, lmac, true);
415 }
416
417 int
418 roc_bphy_cgx_ptp_rx_disable(struct roc_bphy_cgx *roc_cgx, unsigned int lmac)
419 {
420         return roc_bphy_cgx_ptp_rx_ena_dis(roc_cgx, lmac, false);
421 }
422
423 int
424 roc_bphy_cgx_fec_set(struct roc_bphy_cgx *roc_cgx, unsigned int lmac,
425                      enum roc_bphy_cgx_eth_link_fec fec)
426 {
427         uint64_t scr1, scr0;
428
429         if (!roc_cgx)
430                 return -EINVAL;
431
432         if (!roc_bphy_cgx_lmac_exists(roc_cgx, lmac))
433                 return -ENODEV;
434
435         scr1 = FIELD_PREP(SCR1_ETH_CMD_ID, ETH_CMD_SET_FEC) |
436                FIELD_PREP(SCR1_ETH_SET_FEC_ARGS, fec);
437
438         return roc_bphy_cgx_intf_req(roc_cgx, lmac, scr1, &scr0);
439 }
440
441 int
442 roc_bphy_cgx_fec_supported_get(struct roc_bphy_cgx *roc_cgx, unsigned int lmac,
443                                enum roc_bphy_cgx_eth_link_fec *fec)
444 {
445         uint64_t scr1, scr0;
446         int ret;
447
448         if (!roc_cgx || !fec)
449                 return -EINVAL;
450
451         if (!roc_bphy_cgx_lmac_exists(roc_cgx, lmac))
452                 return -ENODEV;
453
454         scr1 = FIELD_PREP(SCR1_ETH_CMD_ID, ETH_CMD_GET_SUPPORTED_FEC);
455
456         ret = roc_bphy_cgx_intf_req(roc_cgx, lmac, scr1, &scr0);
457         if (ret)
458                 return ret;
459
460         scr0 = FIELD_GET(SCR0_ETH_FEC_TYPES_S_FEC, scr0);
461         *fec = (enum roc_bphy_cgx_eth_link_fec)scr0;
462
463         return 0;
464 }
465
466 int
467 roc_bphy_cgx_cpri_mode_change(struct roc_bphy_cgx *roc_cgx, unsigned int lmac,
468                               struct roc_bphy_cgx_cpri_mode_change *mode)
469 {
470         uint64_t scr1, scr0;
471
472         if (!(roc_model_is_cnf95xxn_a0() ||
473               roc_model_is_cnf95xxn_a1() ||
474               roc_model_is_cnf95xxn_b0()))
475                 return -ENOTSUP;
476
477         if (!roc_cgx)
478                 return -EINVAL;
479
480         if (!roc_bphy_cgx_lmac_exists(roc_cgx, lmac))
481                 return -ENODEV;
482
483         if (!mode)
484                 return -EINVAL;
485
486         scr1 = FIELD_PREP(SCR1_ETH_CMD_ID, ETH_CMD_CPRI_MODE_CHANGE) |
487                FIELD_PREP(SCR1_CPRI_MODE_CHANGE_ARGS_GSERC_IDX,
488                           mode->gserc_idx) |
489                FIELD_PREP(SCR1_CPRI_MODE_CHANGE_ARGS_LANE_IDX, mode->lane_idx) |
490                FIELD_PREP(SCR1_CPRI_MODE_CHANGE_ARGS_RATE, mode->rate) |
491                FIELD_PREP(SCR1_CPRI_MODE_CHANGE_ARGS_DISABLE_LEQ,
492                           mode->disable_leq) |
493                FIELD_PREP(SCR1_CPRI_MODE_CHANGE_ARGS_DISABLE_DFE,
494                           mode->disable_dfe);
495
496         return roc_bphy_cgx_intf_req(roc_cgx, lmac, scr1, &scr0);
497 }
498
499 int
500 roc_bphy_cgx_cpri_mode_tx_control(struct roc_bphy_cgx *roc_cgx,
501                                   unsigned int lmac,
502                                   struct roc_bphy_cgx_cpri_mode_tx_ctrl *mode)
503 {
504         uint64_t scr1, scr0;
505
506         if (!(roc_model_is_cnf95xxn_a0() ||
507               roc_model_is_cnf95xxn_a1() ||
508               roc_model_is_cnf95xxn_b0()))
509                 return -ENOTSUP;
510
511         if (!roc_cgx)
512                 return -EINVAL;
513
514         if (!roc_bphy_cgx_lmac_exists(roc_cgx, lmac))
515                 return -ENODEV;
516
517         if (!mode)
518                 return -EINVAL;
519
520         scr1 = FIELD_PREP(SCR1_ETH_CMD_ID, ETH_CMD_CPRI_TX_CONTROL) |
521                FIELD_PREP(SCR1_CPRI_MODE_TX_CTRL_ARGS_GSERC_IDX,
522                           mode->gserc_idx) |
523                FIELD_PREP(SCR1_CPRI_MODE_TX_CTRL_ARGS_LANE_IDX,
524                           mode->lane_idx) |
525                FIELD_PREP(SCR1_CPRI_MODE_TX_CTRL_ARGS_ENABLE, mode->enable);
526
527         return roc_bphy_cgx_intf_req(roc_cgx, lmac, scr1, &scr0);
528 }
529
530 int
531 roc_bphy_cgx_cpri_mode_misc(struct roc_bphy_cgx *roc_cgx, unsigned int lmac,
532                             struct roc_bphy_cgx_cpri_mode_misc *mode)
533 {
534         uint64_t scr1, scr0;
535
536         if (!(roc_model_is_cnf95xxn_a0() ||
537               roc_model_is_cnf95xxn_a1() ||
538               roc_model_is_cnf95xxn_b0()))
539                 return -ENOTSUP;
540
541         if (!roc_cgx)
542                 return -EINVAL;
543
544         if (!roc_bphy_cgx_lmac_exists(roc_cgx, lmac))
545                 return -ENODEV;
546
547         if (!mode)
548                 return -EINVAL;
549
550         scr1 = FIELD_PREP(SCR1_ETH_CMD_ID, ETH_CMD_CPRI_MISC) |
551                FIELD_PREP(SCR1_CPRI_MODE_MISC_ARGS_GSERC_IDX,
552                           mode->gserc_idx) |
553                FIELD_PREP(SCR1_CPRI_MODE_MISC_ARGS_LANE_IDX,
554                           mode->lane_idx) |
555                FIELD_PREP(SCR1_CPRI_MODE_MISC_ARGS_FLAGS, mode->flags);
556
557         return roc_bphy_cgx_intf_req(roc_cgx, lmac, scr1, &scr0);
558 }