2 * Copyright (C) 2015-2017 Netronome Systems, Inc.
4 * This software is dual licensed under the GNU General License Version 2,
5 * June 1991 as shown in the file COPYING in the top-level directory of this
6 * source tree or the BSD 2-Clause License provided below. You have the
7 * option to license this software under the complete terms of either license.
9 * The BSD 2-Clause License:
11 * Redistribution and use in source and binary forms, with or
12 * without modification, are permitted provided that the following
15 * 1. Redistributions of source code must retain the above
16 * copyright notice, this list of conditions and the following
19 * 2. Redistributions in binary form must reproduce the above
20 * copyright notice, this list of conditions and the following
21 * disclaimer in the documentation and/or other materials
22 * provided with the distribution.
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
36 * Authors: Jakub Kicinski <jakub.kicinski@netronome.com>
37 * Jason McMullan <jason.mcmullan@netronome.com>
38 * Francois H. Theron <francois.theron@netronome.com>
41 #include <linux/kernel.h>
42 #include <linux/slab.h>
47 #include "nfp6000/nfp6000.h"
49 /* Init-CSR owner IDs for firmware map to firmware IDs which start at 4.
50 * Lower IDs are reserved for target and loader IDs.
52 #define NFFW_FWID_EXT 3 /* For active MEs that we didn't load. */
53 #define NFFW_FWID_BASE 4
55 #define NFFW_FWID_ALL 255
58 * NFFW_INFO_VERSION history:
59 * 0: This was never actually used (before versioning), but it refers to
60 * the previous struct which had FWINFO_CNT = MEINFO_CNT = 120 that later
62 * 1: First versioned struct, with
68 #define NFFW_INFO_VERSION_CURRENT 2
70 /* Enough for all current chip families */
71 #define NFFW_MEINFO_CNT_V1 120
72 #define NFFW_FWINFO_CNT_V1 120
73 #define NFFW_MEINFO_CNT_V2 200
74 #define NFFW_FWINFO_CNT_V2 200
76 /* Work in 32-bit words to make cross-platform endianness easier to handle */
78 /** nfp.nffw meinfo **/
80 __le32 ctxmask__fwid__meid;
84 __le32 loaded__mu_da__mip_off_hi;
85 __le32 mip_cppid; /* 0 means no MIP */
89 struct nfp_nffw_info_v1 {
90 struct nffw_meinfo meinfo[NFFW_MEINFO_CNT_V1];
91 struct nffw_fwinfo fwinfo[NFFW_FWINFO_CNT_V1];
94 struct nfp_nffw_info_v2 {
95 struct nffw_meinfo meinfo[NFFW_MEINFO_CNT_V2];
96 struct nffw_fwinfo fwinfo[NFFW_FWINFO_CNT_V2];
99 /** Resource: nfp.nffw main **/
100 struct nfp_nffw_info_data {
103 struct nfp_nffw_info_v1 v1;
104 struct nfp_nffw_info_v2 v2;
108 struct nfp_nffw_info {
110 struct nfp_resource *res;
112 struct nfp_nffw_info_data fwinf;
115 /* flg_info_version = flags[0]<27:16>
116 * This is a small version counter intended only to detect if the current
117 * implementation can read the current struct. Struct changes should be very
118 * rare and as such a 12-bit counter should cover large spans of time. By the
119 * time it wraps around, we don't expect to have 4096 versions of this struct
120 * to be in use at the same time.
122 static u32 nffw_res_info_version_get(const struct nfp_nffw_info_data *res)
124 return (le32_to_cpu(res->flags[0]) >> 16) & 0xfff;
127 /* flg_init = flags[0]<0> */
128 static u32 nffw_res_flg_init_get(const struct nfp_nffw_info_data *res)
130 return (le32_to_cpu(res->flags[0]) >> 0) & 1;
133 /* loaded = loaded__mu_da__mip_off_hi<31:31> */
134 static u32 nffw_fwinfo_loaded_get(const struct nffw_fwinfo *fi)
136 return (le32_to_cpu(fi->loaded__mu_da__mip_off_hi) >> 31) & 1;
139 /* mip_cppid = mip_cppid */
140 static u32 nffw_fwinfo_mip_cppid_get(const struct nffw_fwinfo *fi)
142 return le32_to_cpu(fi->mip_cppid);
145 /* loaded = loaded__mu_da__mip_off_hi<8:8> */
146 static u32 nffw_fwinfo_mip_mu_da_get(const struct nffw_fwinfo *fi)
148 return (le32_to_cpu(fi->loaded__mu_da__mip_off_hi) >> 8) & 1;
151 /* mip_offset = (loaded__mu_da__mip_off_hi<7:0> << 8) | mip_offset_lo */
152 static u64 nffw_fwinfo_mip_offset_get(const struct nffw_fwinfo *fi)
154 u64 mip_off_hi = le32_to_cpu(fi->loaded__mu_da__mip_off_hi);
156 return (mip_off_hi & 0xFF) << 32 | le32_to_cpu(fi->mip_offset_lo);
159 #define NFP_IMB_TGTADDRESSMODECFG_MODE_of(_x) (((_x) >> 13) & 0x7)
160 #define NFP_IMB_TGTADDRESSMODECFG_ADDRMODE BIT(12)
161 #define NFP_IMB_TGTADDRESSMODECFG_ADDRMODE_32_BIT 0
162 #define NFP_IMB_TGTADDRESSMODECFG_ADDRMODE_40_BIT BIT(12)
164 static int nfp_mip_mu_locality_lsb(struct nfp_cpp *cpp)
166 unsigned int mode, addr40;
167 u32 xpbaddr, imbcppat;
170 /* Hardcoded XPB IMB Base, island 0 */
171 xpbaddr = 0x000a0000 + NFP_CPP_TARGET_MU * 4;
172 err = nfp_xpb_readl(cpp, xpbaddr, &imbcppat);
176 mode = NFP_IMB_TGTADDRESSMODECFG_MODE_of(imbcppat);
177 addr40 = !!(imbcppat & NFP_IMB_TGTADDRESSMODECFG_ADDRMODE);
179 return nfp_cppat_mu_locality_lsb(mode, addr40);
183 nffw_res_fwinfos(struct nfp_nffw_info_data *fwinf, struct nffw_fwinfo **arr)
185 /* For the this code, version 0 is most likely to be
186 * version 1 in this case. Since the kernel driver
187 * does not take responsibility for initialising the
188 * nfp.nffw resource, any previous code (CA firmware or
189 * userspace) that left the version 0 and did set
190 * the init flag is going to be version 1.
192 switch (nffw_res_info_version_get(fwinf)) {
195 *arr = &fwinf->info.v1.fwinfo[0];
196 return NFFW_FWINFO_CNT_V1;
198 *arr = &fwinf->info.v2.fwinfo[0];
199 return NFFW_FWINFO_CNT_V2;
207 * nfp_nffw_info_open() - Acquire the lock on the NFFW table
208 * @cpp: NFP CPP handle
210 * Return: pointer to nfp_nffw_info object or ERR_PTR()
212 struct nfp_nffw_info *nfp_nffw_info_open(struct nfp_cpp *cpp)
214 struct nfp_nffw_info_data *fwinf;
215 struct nfp_nffw_info *state;
219 state = kzalloc(sizeof(*state), GFP_KERNEL);
221 return ERR_PTR(-ENOMEM);
223 state->res = nfp_resource_acquire(cpp, NFP_RESOURCE_NFP_NFFW);
224 if (IS_ERR(state->res))
227 fwinf = &state->fwinf;
229 if (sizeof(*fwinf) > nfp_resource_size(state->res))
232 err = nfp_cpp_read(cpp, nfp_resource_cpp_id(state->res),
233 nfp_resource_address(state->res),
234 fwinf, sizeof(*fwinf));
235 if (err < (int)sizeof(*fwinf))
238 if (!nffw_res_flg_init_get(fwinf))
241 info_ver = nffw_res_info_version_get(fwinf);
242 if (info_ver > NFFW_INFO_VERSION_CURRENT)
249 nfp_resource_release(state->res);
252 return ERR_PTR(-EIO);
256 * nfp_nffw_info_close() - Release the lock on the NFFW table and free state
257 * @state: NFP FW info state
259 void nfp_nffw_info_close(struct nfp_nffw_info *state)
261 nfp_resource_release(state->res);
266 * nfp_nffw_info_fwid_first() - Return the first firmware ID in the NFFW
267 * @state: NFP FW info state
269 * Return: First NFFW firmware info, NULL on failure
271 static struct nffw_fwinfo *nfp_nffw_info_fwid_first(struct nfp_nffw_info *state)
273 struct nffw_fwinfo *fwinfo;
276 cnt = nffw_res_fwinfos(&state->fwinf, &fwinfo);
280 for (i = 0; i < cnt; i++)
281 if (nffw_fwinfo_loaded_get(&fwinfo[i]))
288 * nfp_nffw_info_mip_first() - Retrieve the location of the first FW's MIP
289 * @state: NFP FW info state
290 * @cpp_id: Pointer to the CPP ID of the MIP
291 * @off: Pointer to the CPP Address of the MIP
293 * Return: 0, or -ERRNO
295 int nfp_nffw_info_mip_first(struct nfp_nffw_info *state, u32 *cpp_id, u64 *off)
297 struct nffw_fwinfo *fwinfo;
299 fwinfo = nfp_nffw_info_fwid_first(state);
303 *cpp_id = nffw_fwinfo_mip_cppid_get(fwinfo);
304 *off = nffw_fwinfo_mip_offset_get(fwinfo);
306 if (nffw_fwinfo_mip_mu_da_get(fwinfo)) {
309 if (NFP_CPP_ID_TARGET_of(*cpp_id) != NFP_CPP_TARGET_MU)
312 locality_off = nfp_mip_mu_locality_lsb(state->cpp);
313 if (locality_off < 0)
316 *off &= ~(NFP_MU_ADDR_ACCESS_TYPE_MASK << locality_off);
317 *off |= NFP_MU_ADDR_ACCESS_TYPE_DIRECT << locality_off;