net/nfp: add NSP user space interface
[dpdk.git] / drivers / net / nfp / nfp_nspu.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <unistd.h>
5 #include <sys/types.h>
6
7 #include <rte_log.h>
8
9 #include "nfp_nfpu.h"
10
11 #define CFG_EXP_BAR_ADDR_SZ     1
12 #define CFG_EXP_BAR_MAP_TYPE    1
13
14 #define EXP_BAR_TARGET_SHIFT     23
15 #define EXP_BAR_LENGTH_SHIFT     27 /* 0=32, 1=64 bit increment */
16 #define EXP_BAR_MAP_TYPE_SHIFT   29 /* Bulk BAR map */
17
18 /* NFP target for NSP access */
19 #define NFP_NSP_TARGET   7
20
21 /*
22  * This is an NFP internal address used for configuring properly an NFP
23  * expansion BAR.
24  */
25 #define MEM_CMD_BASE_ADDR       0x8100000000
26
27 /* NSP interface registers */
28 #define NSP_BASE                (MEM_CMD_BASE_ADDR + 0x22100)
29 #define NSP_STATUS              0x00
30 #define NSP_COMMAND             0x08
31 #define NSP_BUFFER              0x10
32 #define NSP_DEFAULT_BUFFER      0x18
33 #define NSP_DEFAULT_BUFFER_CFG  0x20
34
35 #define NSP_MAGIC                0xab10
36 #define NSP_STATUS_MAGIC(x)      (((x) >> 48) & 0xffff)
37 #define NSP_STATUS_MAJOR(x)      (int)(((x) >> 44) & 0xf)
38 #define NSP_STATUS_MINOR(x)      (int)(((x) >> 32) & 0xfff)
39
40 #define NSP_REG_ADDR(d, off, reg) ((uint8_t *)(d)->mem_base + (off) + (reg))
41 #define NSP_REG_VAL(p) (*(uint64_t *)(p))
42
43 /*
44  * An NFP expansion BAR is configured for allowing access to a specific NFP
45  * target:
46  *
47  *  IN:
48  *      desc: struct with basic NSP addresses to work with
49  *      expbar: NFP PF expansion BAR index to configure
50  *      tgt: NFP target to configure access
51  *      addr: NFP target address
52  *
53  *  OUT:
54  *      pcie_offset: NFP PCI BAR offset to work with
55  */
56 static void
57 nfp_nspu_mem_bar_cfg(nspu_desc_t *desc, int expbar, int tgt,
58                      uint64_t addr, uint64_t *pcie_offset)
59 {
60         uint64_t x, y, barsz;
61         uint32_t *expbar_ptr;
62
63         barsz = desc->barsz;
64
65         /*
66          * NFP CPP address to configure. This comes from NFP 6000
67          * datasheet document based on Bulk mapping.
68          */
69         x = (addr >> (barsz - 3)) << (21 - (40 - (barsz - 3)));
70         x |= CFG_EXP_BAR_MAP_TYPE << EXP_BAR_MAP_TYPE_SHIFT;
71         x |= CFG_EXP_BAR_ADDR_SZ << EXP_BAR_LENGTH_SHIFT;
72         x |= tgt << EXP_BAR_TARGET_SHIFT;
73
74         /* Getting expansion bar configuration register address */
75         expbar_ptr = (uint32_t *)desc->cfg_base;
76         /* Each physical PCI BAR has 8 NFP expansion BARs */
77         expbar_ptr += (desc->pcie_bar * 8) + expbar;
78
79         /* Writing to the expansion BAR register */
80         *expbar_ptr = (uint32_t)x;
81
82         /* Getting the pcie offset to work with from userspace */
83         y = addr & ((uint64_t)(1 << (barsz - 3)) - 1);
84         *pcie_offset = y;
85 }
86
87 /*
88  * Configuring an expansion bar for accessing NSP userspace interface. This
89  * function configures always the same expansion bar, which implies access to
90  * previously configured NFP target is lost.
91  */
92 static void
93 nspu_xlate(nspu_desc_t *desc, uint64_t addr, uint64_t *pcie_offset)
94 {
95         nfp_nspu_mem_bar_cfg(desc, desc->exp_bar, NFP_NSP_TARGET, addr,
96                              pcie_offset);
97 }
98
99 int
100 nfp_nsp_get_abi_version(nspu_desc_t *desc, int *major, int *minor)
101 {
102         uint64_t pcie_offset;
103         uint64_t nsp_reg;
104
105         nspu_xlate(desc, NSP_BASE, &pcie_offset);
106         nsp_reg = NSP_REG_VAL(NSP_REG_ADDR(desc, pcie_offset, NSP_STATUS));
107
108         if (NSP_STATUS_MAGIC(nsp_reg) != NSP_MAGIC)
109                 return -1;
110
111         *major = NSP_STATUS_MAJOR(nsp_reg);
112         *minor = NSP_STATUS_MINOR(nsp_reg);
113
114         return 0;
115 }
116
117 int
118 nfp_nspu_init(nspu_desc_t *desc, int nfp, int pcie_bar, size_t pcie_barsz,
119               int exp_bar, void *exp_bar_cfg_base, void *exp_bar_mmap)
120 {
121         desc->nfp = nfp;
122         desc->pcie_bar = pcie_bar;
123         desc->exp_bar = exp_bar;
124         desc->barsz = pcie_barsz;
125         desc->cfg_base = exp_bar_cfg_base;
126         desc->mem_base = exp_bar_mmap;
127
128         return 0;
129 }