1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2018 Netronome Systems, Inc.
9 #include "nfp6000/nfp6000.h"
10 #include "nfp_resource.h"
13 * flg_info_version = flags[0]<27:16>
14 * This is a small version counter intended only to detect if the current
15 * implementation can read the current struct. Struct changes should be very
16 * rare and as such a 12-bit counter should cover large spans of time. By the
17 * time it wraps around, we don't expect to have 4096 versions of this struct
18 * to be in use at the same time.
21 nffw_res_info_version_get(const struct nfp_nffw_info_data
*res
)
23 return (res
->flags
[0] >> 16) & 0xfff;
26 /* flg_init = flags[0]<0> */
28 nffw_res_flg_init_get(const struct nfp_nffw_info_data
*res
)
30 return (res
->flags
[0] >> 0) & 1;
33 /* loaded = loaded__mu_da__mip_off_hi<31:31> */
35 nffw_fwinfo_loaded_get(const struct nffw_fwinfo
*fi
)
37 return (fi
->loaded__mu_da__mip_off_hi
>> 31) & 1;
40 /* mip_cppid = mip_cppid */
42 nffw_fwinfo_mip_cppid_get(const struct nffw_fwinfo
*fi
)
47 /* loaded = loaded__mu_da__mip_off_hi<8:8> */
49 nffw_fwinfo_mip_mu_da_get(const struct nffw_fwinfo
*fi
)
51 return (fi
->loaded__mu_da__mip_off_hi
>> 8) & 1;
54 /* mip_offset = (loaded__mu_da__mip_off_hi<7:0> << 8) | mip_offset_lo */
56 nffw_fwinfo_mip_offset_get(const struct nffw_fwinfo
*fi
)
58 uint64_t mip_off_hi
= fi
->loaded__mu_da__mip_off_hi
;
60 return (mip_off_hi
& 0xFF) << 32 | fi
->mip_offset_lo
;
63 #define NFP_IMB_TGTADDRESSMODECFG_MODE_of(_x) (((_x) >> 13) & 0x7)
64 #define NFP_IMB_TGTADDRESSMODECFG_ADDRMODE BIT(12)
65 #define NFP_IMB_TGTADDRESSMODECFG_ADDRMODE_32_BIT 0
66 #define NFP_IMB_TGTADDRESSMODECFG_ADDRMODE_40_BIT BIT(12)
69 nfp_mip_mu_locality_lsb(struct nfp_cpp
*cpp
)
71 unsigned int mode
, addr40
;
72 uint32_t xpbaddr
, imbcppat
;
75 /* Hardcoded XPB IMB Base, island 0 */
76 xpbaddr
= 0x000a0000 + NFP_CPP_TARGET_MU
* 4;
77 err
= nfp_xpb_readl(cpp
, xpbaddr
, &imbcppat
);
81 mode
= NFP_IMB_TGTADDRESSMODECFG_MODE_of(imbcppat
);
82 addr40
= !!(imbcppat
& NFP_IMB_TGTADDRESSMODECFG_ADDRMODE
);
84 return nfp_cppat_mu_locality_lsb(mode
, addr40
);
88 nffw_res_fwinfos(struct nfp_nffw_info_data
*fwinf
, struct nffw_fwinfo
**arr
)
91 * For the this code, version 0 is most likely to be version 1 in this
92 * case. Since the kernel driver does not take responsibility for
93 * initialising the nfp.nffw resource, any previous code (CA firmware or
94 * userspace) that left the version 0 and did set the init flag is going
97 switch (nffw_res_info_version_get(fwinf
)) {
100 *arr
= &fwinf
->info
.v1
.fwinfo
[0];
101 return NFFW_FWINFO_CNT_V1
;
103 *arr
= &fwinf
->info
.v2
.fwinfo
[0];
104 return NFFW_FWINFO_CNT_V2
;
112 * nfp_nffw_info_open() - Acquire the lock on the NFFW table
113 * @cpp: NFP CPP handle
115 * Return: 0, or -ERRNO
117 struct nfp_nffw_info
*
118 nfp_nffw_info_open(struct nfp_cpp
*cpp
)
120 struct nfp_nffw_info_data
*fwinf
;
121 struct nfp_nffw_info
*state
;
125 state
= malloc(sizeof(*state
));
129 memset(state
, 0, sizeof(*state
));
131 state
->res
= nfp_resource_acquire(cpp
, NFP_RESOURCE_NFP_NFFW
);
135 fwinf
= &state
->fwinf
;
137 if (sizeof(*fwinf
) > nfp_resource_size(state
->res
))
140 err
= nfp_cpp_read(cpp
, nfp_resource_cpp_id(state
->res
),
141 nfp_resource_address(state
->res
),
142 fwinf
, sizeof(*fwinf
));
143 if (err
< (int)sizeof(*fwinf
))
146 if (!nffw_res_flg_init_get(fwinf
))
149 info_ver
= nffw_res_info_version_get(fwinf
);
150 if (info_ver
> NFFW_INFO_VERSION_CURRENT
)
157 nfp_resource_release(state
->res
);
164 * nfp_nffw_info_release() - Release the lock on the NFFW table
165 * @state: NFP FW info state
167 * Return: 0, or -ERRNO
170 nfp_nffw_info_close(struct nfp_nffw_info
*state
)
172 nfp_resource_release(state
->res
);
177 * nfp_nffw_info_fwid_first() - Return the first firmware ID in the NFFW
178 * @state: NFP FW info state
180 * Return: First NFFW firmware info, NULL on failure
182 static struct nffw_fwinfo
*
183 nfp_nffw_info_fwid_first(struct nfp_nffw_info
*state
)
185 struct nffw_fwinfo
*fwinfo
;
188 cnt
= nffw_res_fwinfos(&state
->fwinf
, &fwinfo
);
192 for (i
= 0; i
< cnt
; i
++)
193 if (nffw_fwinfo_loaded_get(&fwinfo
[i
]))
200 * nfp_nffw_info_mip_first() - Retrieve the location of the first FW's MIP
201 * @state: NFP FW info state
202 * @cpp_id: Pointer to the CPP ID of the MIP
203 * @off: Pointer to the CPP Address of the MIP
205 * Return: 0, or -ERRNO
208 nfp_nffw_info_mip_first(struct nfp_nffw_info
*state
, uint32_t *cpp_id
,
211 struct nffw_fwinfo
*fwinfo
;
213 fwinfo
= nfp_nffw_info_fwid_first(state
);
217 *cpp_id
= nffw_fwinfo_mip_cppid_get(fwinfo
);
218 *off
= nffw_fwinfo_mip_offset_get(fwinfo
);
220 if (nffw_fwinfo_mip_mu_da_get(fwinfo
)) {
223 if (NFP_CPP_ID_TARGET_of(*cpp_id
) != NFP_CPP_TARGET_MU
)
226 locality_off
= nfp_mip_mu_locality_lsb(state
->cpp
);
227 if (locality_off
< 0)
230 *off
&= ~(NFP_MU_ADDR_ACCESS_TYPE_MASK
<< locality_off
);
231 *off
|= NFP_MU_ADDR_ACCESS_TYPE_DIRECT
<< locality_off
;