14610ac93SAndrew Boyer /* SPDX-License-Identifier: BSD-3-Clause
24610ac93SAndrew Boyer * Copyright 2021-2024 Advanced Micro Devices, Inc.
34610ac93SAndrew Boyer */
44610ac93SAndrew Boyer
54610ac93SAndrew Boyer #include <stdint.h>
64610ac93SAndrew Boyer #include <errno.h>
74610ac93SAndrew Boyer
84610ac93SAndrew Boyer #include <rte_errno.h>
94610ac93SAndrew Boyer #include <rte_common.h>
104610ac93SAndrew Boyer #include <rte_log.h>
114610ac93SAndrew Boyer #include <rte_eal.h>
124610ac93SAndrew Boyer #include <bus_vdev_driver.h>
134610ac93SAndrew Boyer #include <rte_dev.h>
144610ac93SAndrew Boyer #include <rte_string_fns.h>
154610ac93SAndrew Boyer
164610ac93SAndrew Boyer #include "ionic_crypto.h"
174610ac93SAndrew Boyer
184610ac93SAndrew Boyer #define IOCPT_VDEV_DEV_BAR 0
194610ac93SAndrew Boyer #define IOCPT_VDEV_INTR_CTL_BAR 1
204610ac93SAndrew Boyer #define IOCPT_VDEV_INTR_CFG_BAR 2
214610ac93SAndrew Boyer #define IOCPT_VDEV_DB_BAR 3
224610ac93SAndrew Boyer #define IOCPT_VDEV_BARS_MAX 4
234610ac93SAndrew Boyer
244610ac93SAndrew Boyer #define IOCPT_VDEV_DEV_INFO_REGS_OFFSET 0x0000
254610ac93SAndrew Boyer #define IOCPT_VDEV_DEV_CMD_REGS_OFFSET 0x0800
264610ac93SAndrew Boyer
27*25c896eaSAndrew Boyer #define IOCPT_VDEV_FW_WAIT_US 1000 /* 1ms */
28*25c896eaSAndrew Boyer #define IOCPT_VDEV_FW_WAIT_MAX 5000 /* 5s */
29*25c896eaSAndrew Boyer
304610ac93SAndrew Boyer static int
iocpt_vdev_setup_bars(struct iocpt_dev * dev)314610ac93SAndrew Boyer iocpt_vdev_setup_bars(struct iocpt_dev *dev)
324610ac93SAndrew Boyer {
33*25c896eaSAndrew Boyer struct iocpt_dev_bars *bars = &dev->bars;
34*25c896eaSAndrew Boyer uint8_t *bar0_base;
35*25c896eaSAndrew Boyer uint32_t fw_waits = 0;
36*25c896eaSAndrew Boyer uint8_t fw;
37*25c896eaSAndrew Boyer
384610ac93SAndrew Boyer IOCPT_PRINT_CALL();
394610ac93SAndrew Boyer
40*25c896eaSAndrew Boyer /* BAR0: dev_cmd */
41*25c896eaSAndrew Boyer bar0_base = bars->bar[IOCPT_VDEV_DEV_BAR].vaddr;
42*25c896eaSAndrew Boyer dev->dev_info = (union iocpt_dev_info_regs *)
43*25c896eaSAndrew Boyer &bar0_base[IOCPT_VDEV_DEV_INFO_REGS_OFFSET];
44*25c896eaSAndrew Boyer dev->dev_cmd = (union iocpt_dev_cmd_regs *)
45*25c896eaSAndrew Boyer &bar0_base[IOCPT_VDEV_DEV_CMD_REGS_OFFSET];
46*25c896eaSAndrew Boyer
47*25c896eaSAndrew Boyer /* BAR1: interrupts */
48*25c896eaSAndrew Boyer dev->intr_ctrl = (void *)bars->bar[IOCPT_VDEV_INTR_CTL_BAR].vaddr;
49*25c896eaSAndrew Boyer
50*25c896eaSAndrew Boyer /* BAR3: doorbells */
51*25c896eaSAndrew Boyer dev->db_pages = (void *)bars->bar[IOCPT_VDEV_DB_BAR].vaddr;
52*25c896eaSAndrew Boyer
53*25c896eaSAndrew Boyer /* Wait for the FW to indicate readiness */
54*25c896eaSAndrew Boyer while (1) {
55*25c896eaSAndrew Boyer fw = ioread8(&dev->dev_info->fw_status);
56*25c896eaSAndrew Boyer if ((fw & IOCPT_FW_STS_F_RUNNING) != 0)
57*25c896eaSAndrew Boyer break;
58*25c896eaSAndrew Boyer
59*25c896eaSAndrew Boyer if (fw_waits > IOCPT_VDEV_FW_WAIT_MAX) {
60*25c896eaSAndrew Boyer IOCPT_PRINT(ERR, "Firmware readiness bit not set");
61*25c896eaSAndrew Boyer return -ETIMEDOUT;
62*25c896eaSAndrew Boyer }
63*25c896eaSAndrew Boyer
64*25c896eaSAndrew Boyer fw_waits++;
65*25c896eaSAndrew Boyer rte_delay_us_block(IOCPT_VDEV_FW_WAIT_US);
66*25c896eaSAndrew Boyer }
67*25c896eaSAndrew Boyer IOCPT_PRINT(DEBUG, "Firmware ready (%u waits)", fw_waits);
68*25c896eaSAndrew Boyer
694610ac93SAndrew Boyer dev->name = rte_vdev_device_name(dev->bus_dev);
704610ac93SAndrew Boyer
714610ac93SAndrew Boyer return 0;
724610ac93SAndrew Boyer }
734610ac93SAndrew Boyer
744610ac93SAndrew Boyer static void
iocpt_vdev_unmap_bars(struct iocpt_dev * dev)754610ac93SAndrew Boyer iocpt_vdev_unmap_bars(struct iocpt_dev *dev)
764610ac93SAndrew Boyer {
774610ac93SAndrew Boyer struct iocpt_dev_bars *bars = &dev->bars;
784610ac93SAndrew Boyer uint32_t i;
794610ac93SAndrew Boyer
804610ac93SAndrew Boyer for (i = 0; i < IOCPT_VDEV_BARS_MAX; i++)
814610ac93SAndrew Boyer ionic_uio_rel_rsrc(dev->name, i, &bars->bar[i]);
824610ac93SAndrew Boyer }
834610ac93SAndrew Boyer
844610ac93SAndrew Boyer static uint8_t iocpt_vdev_driver_id;
854610ac93SAndrew Boyer static const struct iocpt_dev_intf iocpt_vdev_intf = {
864610ac93SAndrew Boyer .setup_bars = iocpt_vdev_setup_bars,
874610ac93SAndrew Boyer .unmap_bars = iocpt_vdev_unmap_bars,
884610ac93SAndrew Boyer };
894610ac93SAndrew Boyer
904610ac93SAndrew Boyer static int
iocpt_vdev_probe(struct rte_vdev_device * vdev)914610ac93SAndrew Boyer iocpt_vdev_probe(struct rte_vdev_device *vdev)
924610ac93SAndrew Boyer {
934610ac93SAndrew Boyer struct iocpt_dev_bars bars = {};
944610ac93SAndrew Boyer const char *name = rte_vdev_device_name(vdev);
954610ac93SAndrew Boyer unsigned int i;
964610ac93SAndrew Boyer
974610ac93SAndrew Boyer IOCPT_PRINT(NOTICE, "Initializing device %s%s", name,
984610ac93SAndrew Boyer rte_eal_process_type() == RTE_PROC_SECONDARY ?
994610ac93SAndrew Boyer " [SECONDARY]" : "");
1004610ac93SAndrew Boyer
1014610ac93SAndrew Boyer ionic_uio_scan_mcrypt_devices();
1024610ac93SAndrew Boyer
1034610ac93SAndrew Boyer for (i = 0; i < IOCPT_VDEV_BARS_MAX; i++)
1044610ac93SAndrew Boyer ionic_uio_get_rsrc(name, i, &bars.bar[i]);
1054610ac93SAndrew Boyer
1064610ac93SAndrew Boyer bars.num_bars = IOCPT_VDEV_BARS_MAX;
1074610ac93SAndrew Boyer
1084610ac93SAndrew Boyer return iocpt_probe((void *)vdev, &vdev->device,
1094610ac93SAndrew Boyer &bars, &iocpt_vdev_intf,
1104610ac93SAndrew Boyer iocpt_vdev_driver_id, rte_socket_id());
1114610ac93SAndrew Boyer }
1124610ac93SAndrew Boyer
1134610ac93SAndrew Boyer static int
iocpt_vdev_remove(struct rte_vdev_device * vdev)1144610ac93SAndrew Boyer iocpt_vdev_remove(struct rte_vdev_device *vdev)
1154610ac93SAndrew Boyer {
1164610ac93SAndrew Boyer return iocpt_remove(&vdev->device);
1174610ac93SAndrew Boyer }
1184610ac93SAndrew Boyer
1194610ac93SAndrew Boyer static struct rte_vdev_driver rte_vdev_iocpt_pmd = {
1204610ac93SAndrew Boyer .probe = iocpt_vdev_probe,
1214610ac93SAndrew Boyer .remove = iocpt_vdev_remove,
1224610ac93SAndrew Boyer };
1234610ac93SAndrew Boyer
1244610ac93SAndrew Boyer static struct cryptodev_driver rte_vdev_iocpt_drv;
1254610ac93SAndrew Boyer
1264610ac93SAndrew Boyer RTE_PMD_REGISTER_VDEV(crypto_ionic, rte_vdev_iocpt_pmd);
1274610ac93SAndrew Boyer RTE_PMD_REGISTER_CRYPTO_DRIVER(rte_vdev_iocpt_drv, rte_vdev_iocpt_pmd.driver,
1284610ac93SAndrew Boyer iocpt_vdev_driver_id);
129