xref: /dpdk/drivers/net/nfp/nfpcore/nfp_cppcore.c (revision b6de43530dfa30cbf6b70857e3835099701063d4)
1c7e9729dSAlejandro Lucero /* SPDX-License-Identifier: BSD-3-Clause
2c7e9729dSAlejandro Lucero  * Copyright(c) 2018 Netronome Systems, Inc.
3c7e9729dSAlejandro Lucero  * All rights reserved.
4c7e9729dSAlejandro Lucero  */
5c7e9729dSAlejandro Lucero 
6ff627b74SChaoyong He #include "nfp_cpp.h"
7c7e9729dSAlejandro Lucero 
8a3460357SChaoyong He #include <nfp_platform.h>
9a3460357SChaoyong He 
1052d810dcSJames Hershaw #include "nfp_logs.h"
11055ccb33SChaoyong He #include "nfp_target.h"
12c7e9729dSAlejandro Lucero #include "nfp6000/nfp6000.h"
13c7e9729dSAlejandro Lucero #include "nfp6000/nfp_xpb.h"
14e96559a1SChaoyong He #include "nfp6000_pcie.h"
15c7e9729dSAlejandro Lucero 
16ff627b74SChaoyong He #define NFP_PL_DEVICE_PART_NFP6000              0x6200
17c7e9729dSAlejandro Lucero #define NFP_PL_DEVICE_ID                        0x00000004
18c7e9729dSAlejandro Lucero #define NFP_PL_DEVICE_ID_MASK                   0xff
19c0a8b024SHeinrich Kuhn #define NFP_PL_DEVICE_PART_MASK                 0xffff0000
20c0a8b024SHeinrich Kuhn #define NFP_PL_DEVICE_MODEL_MASK               (NFP_PL_DEVICE_PART_MASK | \
21c0a8b024SHeinrich Kuhn 						NFP_PL_DEVICE_ID_MASK)
22c7e9729dSAlejandro Lucero 
23ff627b74SChaoyong He /* NFP CPP handle */
24ff627b74SChaoyong He struct nfp_cpp {
25ff627b74SChaoyong He 	void *priv;  /**< Private data of the low-level implementation */
26ff627b74SChaoyong He 
27ff627b74SChaoyong He 	uint32_t model;  /**< Chip model */
28ff627b74SChaoyong He 	uint16_t interface;  /**< Chip interface id */
29ff627b74SChaoyong He 	uint8_t serial[NFP_SERIAL_LEN];  /**< Chip serial number */
30ff627b74SChaoyong He 
31ff627b74SChaoyong He 	/** Low-level implementation ops */
32ff627b74SChaoyong He 	const struct nfp_cpp_operations *op;
33ff627b74SChaoyong He 
34ff627b74SChaoyong He 	/*
35ff627b74SChaoyong He 	 * NFP-6xxx originating island IMB CPP Address Translation. CPP Target
36ff627b74SChaoyong He 	 * ID is index into array. Values are obtained at runtime from local
37ff627b74SChaoyong He 	 * island XPB CSRs.
38ff627b74SChaoyong He 	 */
39ff627b74SChaoyong He 	uint32_t imb_cat_table[16];
40ff627b74SChaoyong He 
41ff627b74SChaoyong He 	/**< MU access type bit offset */
42ff627b74SChaoyong He 	uint32_t mu_locality_lsb;
43ff627b74SChaoyong He 
44ff627b74SChaoyong He 	bool driver_lock_needed;
45ff627b74SChaoyong He };
46ff627b74SChaoyong He 
47ff627b74SChaoyong He /* NFP CPP device area handle */
48ff627b74SChaoyong He struct nfp_cpp_area {
49ff627b74SChaoyong He 	struct nfp_cpp *cpp;
50ff627b74SChaoyong He 	char *name;
51ff627b74SChaoyong He 	uint64_t offset;
52ff627b74SChaoyong He 	uint32_t size;
53ff627b74SChaoyong He 	/* Here follows the 'priv' part of nfp_cpp_area. */
54ff627b74SChaoyong He 	/* Here follows the ASCII name, pointed by @name */
55ff627b74SChaoyong He };
56ff627b74SChaoyong He 
576d03aa61SChaoyong He /**
586d03aa61SChaoyong He  * Set the private data of the nfp_cpp instance
596d03aa61SChaoyong He  *
606d03aa61SChaoyong He  * @param cpp
616d03aa61SChaoyong He  *   NFP CPP operations structure
626d03aa61SChaoyong He  *
636d03aa61SChaoyong He  * @return
646d03aa61SChaoyong He  *   Opaque device pointer
656d03aa61SChaoyong He  */
66c7e9729dSAlejandro Lucero void
67d108b9e9SChaoyong He nfp_cpp_priv_set(struct nfp_cpp *cpp,
68d108b9e9SChaoyong He 		void *priv)
69c7e9729dSAlejandro Lucero {
70c7e9729dSAlejandro Lucero 	cpp->priv = priv;
71c7e9729dSAlejandro Lucero }
72c7e9729dSAlejandro Lucero 
736d03aa61SChaoyong He /**
746d03aa61SChaoyong He  * Return the private data of the nfp_cpp instance
756d03aa61SChaoyong He  *
766d03aa61SChaoyong He  * @param cpp
776d03aa61SChaoyong He  *   NFP CPP operations structure
786d03aa61SChaoyong He  *
796d03aa61SChaoyong He  * @return
806d03aa61SChaoyong He  *   Opaque device pointer
816d03aa61SChaoyong He  */
82c7e9729dSAlejandro Lucero void *
83c7e9729dSAlejandro Lucero nfp_cpp_priv(struct nfp_cpp *cpp)
84c7e9729dSAlejandro Lucero {
85c7e9729dSAlejandro Lucero 	return cpp->priv;
86c7e9729dSAlejandro Lucero }
87c7e9729dSAlejandro Lucero 
886d03aa61SChaoyong He /**
896d03aa61SChaoyong He  * Set the model id
906d03aa61SChaoyong He  *
916d03aa61SChaoyong He  * @param cpp
926d03aa61SChaoyong He  *   NFP CPP operations structure
936d03aa61SChaoyong He  * @param model
946d03aa61SChaoyong He  *   Model ID
956d03aa61SChaoyong He  */
96c7e9729dSAlejandro Lucero void
97d108b9e9SChaoyong He nfp_cpp_model_set(struct nfp_cpp *cpp,
98d108b9e9SChaoyong He 		uint32_t model)
99c7e9729dSAlejandro Lucero {
100c7e9729dSAlejandro Lucero 	cpp->model = model;
101c7e9729dSAlejandro Lucero }
102c7e9729dSAlejandro Lucero 
1036d03aa61SChaoyong He /**
1046d03aa61SChaoyong He  * Retrieve the Model ID of the NFP
1056d03aa61SChaoyong He  *
1066d03aa61SChaoyong He  * @param cpp
1076d03aa61SChaoyong He  *   NFP CPP handle
1086d03aa61SChaoyong He  *
1096d03aa61SChaoyong He  * @return
1106d03aa61SChaoyong He  *   NFP CPP Model ID
1116d03aa61SChaoyong He  */
112c7e9729dSAlejandro Lucero uint32_t
113c7e9729dSAlejandro Lucero nfp_cpp_model(struct nfp_cpp *cpp)
114c7e9729dSAlejandro Lucero {
115c0a8b024SHeinrich Kuhn 	int err;
116c0a8b024SHeinrich Kuhn 	uint32_t model;
117c0a8b024SHeinrich Kuhn 
118cbcbfd73SJames Hershaw 	if (cpp == NULL)
119c7e9729dSAlejandro Lucero 		return NFP_CPP_MODEL_INVALID;
120c7e9729dSAlejandro Lucero 
121588c5b10SChaoyong He 	err = nfp_cpp_model_autodetect(cpp, &model);
122c7e9729dSAlejandro Lucero 
123c0a8b024SHeinrich Kuhn 	if (err < 0)
124c0a8b024SHeinrich Kuhn 		return err;
125c0a8b024SHeinrich Kuhn 
126c0a8b024SHeinrich Kuhn 	return model;
127c7e9729dSAlejandro Lucero }
128c7e9729dSAlejandro Lucero 
1296d03aa61SChaoyong He /**
1306d03aa61SChaoyong He  * Set the private instance owned data of a nfp_cpp struct
1316d03aa61SChaoyong He  *
1326d03aa61SChaoyong He  * @param cpp
1336d03aa61SChaoyong He  *   NFP CPP operations structure
1346d03aa61SChaoyong He  * @param interface
1356d03aa61SChaoyong He  *   Interface ID
1366d03aa61SChaoyong He  */
137c7e9729dSAlejandro Lucero void
138d108b9e9SChaoyong He nfp_cpp_interface_set(struct nfp_cpp *cpp,
139d108b9e9SChaoyong He 		uint32_t interface)
140c7e9729dSAlejandro Lucero {
141c7e9729dSAlejandro Lucero 	cpp->interface = interface;
142c7e9729dSAlejandro Lucero }
143c7e9729dSAlejandro Lucero 
1446d03aa61SChaoyong He /**
1456d03aa61SChaoyong He  * Retrieve the Serial ID of the NFP
1466d03aa61SChaoyong He  *
1476d03aa61SChaoyong He  * @param cpp
1486d03aa61SChaoyong He  *   NFP CPP handle
1496d03aa61SChaoyong He  * @param serial
1506d03aa61SChaoyong He  *   Pointer to NFP serial number
1516d03aa61SChaoyong He  *
1526d03aa61SChaoyong He  * @return
1536d03aa61SChaoyong He  *   Length of NFP serial number
1546d03aa61SChaoyong He  */
155ff627b74SChaoyong He uint32_t
156d108b9e9SChaoyong He nfp_cpp_serial(struct nfp_cpp *cpp,
157d108b9e9SChaoyong He 		const uint8_t **serial)
158c7e9729dSAlejandro Lucero {
159ff627b74SChaoyong He 	*serial = &cpp->serial[0];
160ff627b74SChaoyong He 
161ff627b74SChaoyong He 	return sizeof(cpp->serial);
162c7e9729dSAlejandro Lucero }
163c7e9729dSAlejandro Lucero 
1646d03aa61SChaoyong He /**
1656d03aa61SChaoyong He  * Set the private instance owned data of a nfp_cpp struct
1666d03aa61SChaoyong He  *
1676d03aa61SChaoyong He  * @param cpp
1686d03aa61SChaoyong He  *   NFP CPP operations structure
1696d03aa61SChaoyong He  * @param serial
1706d03aa61SChaoyong He  *   NFP serial byte array
1716d03aa61SChaoyong He  * @param serial_len
1726d03aa61SChaoyong He  *   Length of the serial byte array
1736d03aa61SChaoyong He  */
174ff627b74SChaoyong He void
175d108b9e9SChaoyong He nfp_cpp_serial_set(struct nfp_cpp *cpp,
176d108b9e9SChaoyong He 		const uint8_t *serial,
177c7e9729dSAlejandro Lucero 		size_t serial_len)
178c7e9729dSAlejandro Lucero {
179c7e9729dSAlejandro Lucero 	memcpy(cpp->serial, serial, serial_len);
180c7e9729dSAlejandro Lucero }
181c7e9729dSAlejandro Lucero 
1826d03aa61SChaoyong He /**
1836d03aa61SChaoyong He  * Retrieve the Interface ID of the NFP
1846d03aa61SChaoyong He  *
1856d03aa61SChaoyong He  * @param cpp
1866d03aa61SChaoyong He  *   NFP CPP handle
1876d03aa61SChaoyong He  *
1886d03aa61SChaoyong He  * @return
1896d03aa61SChaoyong He  *   NFP CPP Interface ID
1906d03aa61SChaoyong He  */
191c7e9729dSAlejandro Lucero uint16_t
192c7e9729dSAlejandro Lucero nfp_cpp_interface(struct nfp_cpp *cpp)
193c7e9729dSAlejandro Lucero {
194cbcbfd73SJames Hershaw 	if (cpp == NULL)
195c7e9729dSAlejandro Lucero 		return NFP_CPP_INTERFACE(NFP_CPP_INTERFACE_TYPE_INVALID, 0, 0);
196c7e9729dSAlejandro Lucero 
197c7e9729dSAlejandro Lucero 	return cpp->interface;
198c7e9729dSAlejandro Lucero }
199c7e9729dSAlejandro Lucero 
2006d03aa61SChaoyong He /**
201ff627b74SChaoyong He  * Retrieve the driver need lock flag
202ff627b74SChaoyong He  *
203ff627b74SChaoyong He  * @param cpp
204ff627b74SChaoyong He  *   NFP CPP handle
205ff627b74SChaoyong He  *
206ff627b74SChaoyong He  * @return
207ff627b74SChaoyong He  *   The driver need lock flag
208ff627b74SChaoyong He  */
209ff627b74SChaoyong He bool
210ff627b74SChaoyong He nfp_cpp_driver_need_lock(const struct nfp_cpp *cpp)
211ff627b74SChaoyong He {
212ff627b74SChaoyong He 	return cpp->driver_lock_needed;
213ff627b74SChaoyong He }
214ff627b74SChaoyong He 
215ff627b74SChaoyong He /**
2166d03aa61SChaoyong He  * Get the privately allocated portion of a NFP CPP area handle
2176d03aa61SChaoyong He  *
2186d03aa61SChaoyong He  * @param cpp_area
2196d03aa61SChaoyong He  *   NFP CPP area handle
2206d03aa61SChaoyong He  *
2216d03aa61SChaoyong He  * @return
2226d03aa61SChaoyong He  *   Pointer to the private area, or NULL on failure
2236d03aa61SChaoyong He  */
224c7e9729dSAlejandro Lucero void *
225c7e9729dSAlejandro Lucero nfp_cpp_area_priv(struct nfp_cpp_area *cpp_area)
226c7e9729dSAlejandro Lucero {
227c7e9729dSAlejandro Lucero 	return &cpp_area[1];
228c7e9729dSAlejandro Lucero }
229c7e9729dSAlejandro Lucero 
2306d03aa61SChaoyong He /**
2316d03aa61SChaoyong He  * Get the NFP CPP handle that is the pci_dev of a NFP CPP area handle
2326d03aa61SChaoyong He  *
2336d03aa61SChaoyong He  * @param cpp_area
2346d03aa61SChaoyong He  *   NFP CPP area handle
2356d03aa61SChaoyong He  *
2366d03aa61SChaoyong He  * @return
2376d03aa61SChaoyong He  *   NFP CPP handle
2386d03aa61SChaoyong He  */
239c7e9729dSAlejandro Lucero struct nfp_cpp *
240c7e9729dSAlejandro Lucero nfp_cpp_area_cpp(struct nfp_cpp_area *cpp_area)
241c7e9729dSAlejandro Lucero {
242c7e9729dSAlejandro Lucero 	return cpp_area->cpp;
243c7e9729dSAlejandro Lucero }
244c7e9729dSAlejandro Lucero 
2456d03aa61SChaoyong He /**
2466d03aa61SChaoyong He  * Get the name passed during allocation of the NFP CPP area handle
2476d03aa61SChaoyong He  *
2486d03aa61SChaoyong He  * @param cpp_area
2496d03aa61SChaoyong He  *   NFP CPP area handle
2506d03aa61SChaoyong He  *
2516d03aa61SChaoyong He  * @return
2526d03aa61SChaoyong He  *   Pointer to the area's name
2536d03aa61SChaoyong He  */
254c7e9729dSAlejandro Lucero const char *
255c7e9729dSAlejandro Lucero nfp_cpp_area_name(struct nfp_cpp_area *cpp_area)
256c7e9729dSAlejandro Lucero {
257c7e9729dSAlejandro Lucero 	return cpp_area->name;
258c7e9729dSAlejandro Lucero }
259c7e9729dSAlejandro Lucero 
260925c27ecSChaoyong He #define NFP_IMB_TGTADDRESSMODECFG_MODE_of(_x)       (((_x) >> 13) & 0x7)
261925c27ecSChaoyong He #define NFP_IMB_TGTADDRESSMODECFG_ADDRMODE          RTE_BIT32(12)
262925c27ecSChaoyong He 
263925c27ecSChaoyong He static int
264925c27ecSChaoyong He nfp_cpp_set_mu_locality_lsb(struct nfp_cpp *cpp)
265925c27ecSChaoyong He {
266925c27ecSChaoyong He 	int ret;
267925c27ecSChaoyong He 	int mode;
268925c27ecSChaoyong He 	int addr40;
269925c27ecSChaoyong He 	uint32_t imbcppat;
270925c27ecSChaoyong He 
271925c27ecSChaoyong He 	imbcppat = cpp->imb_cat_table[NFP_CPP_TARGET_MU];
272925c27ecSChaoyong He 	mode = NFP_IMB_TGTADDRESSMODECFG_MODE_of(imbcppat);
273925c27ecSChaoyong He 	addr40 = imbcppat & NFP_IMB_TGTADDRESSMODECFG_ADDRMODE;
274925c27ecSChaoyong He 
275925c27ecSChaoyong He 	ret = nfp_cppat_mu_locality_lsb(mode, addr40);
276925c27ecSChaoyong He 	if (ret < 0)
277925c27ecSChaoyong He 		return ret;
278925c27ecSChaoyong He 
279925c27ecSChaoyong He 	cpp->mu_locality_lsb = ret;
280925c27ecSChaoyong He 
281925c27ecSChaoyong He 	return 0;
282925c27ecSChaoyong He }
283925c27ecSChaoyong He 
284925c27ecSChaoyong He uint32_t
285925c27ecSChaoyong He nfp_cpp_mu_locality_lsb(struct nfp_cpp *cpp)
286925c27ecSChaoyong He {
287925c27ecSChaoyong He 	return cpp->mu_locality_lsb;
288925c27ecSChaoyong He }
289925c27ecSChaoyong He 
2906d03aa61SChaoyong He /**
2916d03aa61SChaoyong He  * Allocate and initialize a CPP area structure.
2926d03aa61SChaoyong He  * The area must later be locked down with an 'acquire' before
2936d03aa61SChaoyong He  * it can be safely accessed.
294c7e9729dSAlejandro Lucero  *
2956d03aa61SChaoyong He  * @param cpp
2966d03aa61SChaoyong He  *   CPP device handle
2976d03aa61SChaoyong He  * @param dest
2986d03aa61SChaoyong He  *   CPP id
2996d03aa61SChaoyong He  * @param name
3006d03aa61SChaoyong He  *   Name of region
3016d03aa61SChaoyong He  * @param address
3026d03aa61SChaoyong He  *   Address of region
3036d03aa61SChaoyong He  * @param size
3046d03aa61SChaoyong He  *   Size of region
3056d03aa61SChaoyong He  *
3066d03aa61SChaoyong He  * @return
3076d03aa61SChaoyong He  *   NFP CPP area handle, or NULL
308c7e9729dSAlejandro Lucero  *
309c7e9729dSAlejandro Lucero  * NOTE: @address and @size must be 32-bit aligned values.
310c7e9729dSAlejandro Lucero  */
311c7e9729dSAlejandro Lucero struct nfp_cpp_area *
312d108b9e9SChaoyong He nfp_cpp_area_alloc_with_name(struct nfp_cpp *cpp,
313d108b9e9SChaoyong He 		uint32_t dest,
314d108b9e9SChaoyong He 		const char *name,
315c69debceSChaoyong He 		uint64_t address,
316c69debceSChaoyong He 		uint32_t size)
317c7e9729dSAlejandro Lucero {
318610bf14bSChaoyong He 	int err;
319ff627b74SChaoyong He 	size_t name_len;
320ff627b74SChaoyong He 	uint32_t target_id;
321ff627b74SChaoyong He 	uint64_t target_addr;
322c7e9729dSAlejandro Lucero 	struct nfp_cpp_area *area;
323c7e9729dSAlejandro Lucero 
324cbcbfd73SJames Hershaw 	if (cpp == NULL)
325c7e9729dSAlejandro Lucero 		return NULL;
326c7e9729dSAlejandro Lucero 
327c7e9729dSAlejandro Lucero 	/* Remap from cpp_island to cpp_target */
328ff627b74SChaoyong He 	err = nfp_target_cpp(dest, address, &target_id, &target_addr,
329ff627b74SChaoyong He 			cpp->imb_cat_table);
330c7e9729dSAlejandro Lucero 	if (err < 0)
331c7e9729dSAlejandro Lucero 		return NULL;
332c7e9729dSAlejandro Lucero 
333cbcbfd73SJames Hershaw 	if (name == NULL)
334ff627b74SChaoyong He 		name = "(reserved)";
335c7e9729dSAlejandro Lucero 
336ff627b74SChaoyong He 	name_len = strlen(name) + 1;
337ff627b74SChaoyong He 	area = calloc(1, sizeof(*area) + cpp->op->area_priv_size + name_len);
338cbcbfd73SJames Hershaw 	if (area == NULL)
339c7e9729dSAlejandro Lucero 		return NULL;
340c7e9729dSAlejandro Lucero 
341c7e9729dSAlejandro Lucero 	area->cpp = cpp;
342c7e9729dSAlejandro Lucero 	area->name = ((char *)area) + sizeof(*area) + cpp->op->area_priv_size;
343ff627b74SChaoyong He 	memcpy(area->name, name, name_len);
344c7e9729dSAlejandro Lucero 
345ff627b74SChaoyong He 	err = cpp->op->area_init(area, target_id, target_addr, size);
346c7e9729dSAlejandro Lucero 	if (err < 0) {
347*b6de4353SZerun Fu 		PMD_DRV_LOG(ERR, "Area init op failed.");
348c7e9729dSAlejandro Lucero 		free(area);
349c7e9729dSAlejandro Lucero 		return NULL;
350c7e9729dSAlejandro Lucero 	}
351c7e9729dSAlejandro Lucero 
352ff627b74SChaoyong He 	area->offset = target_addr;
353c7e9729dSAlejandro Lucero 	area->size = size;
354c7e9729dSAlejandro Lucero 
355c7e9729dSAlejandro Lucero 	return area;
356c7e9729dSAlejandro Lucero }
357c7e9729dSAlejandro Lucero 
3586d03aa61SChaoyong He /**
3596d03aa61SChaoyong He  * Allocate and initialize a CPP area structure.
3606d03aa61SChaoyong He  * The area must later be locked down with an 'acquire' before
3616d03aa61SChaoyong He  * it can be safely accessed.
3626d03aa61SChaoyong He  *
3636d03aa61SChaoyong He  * @param cpp
3646d03aa61SChaoyong He  *   CPP device handle
3656d03aa61SChaoyong He  * @param dest
3666d03aa61SChaoyong He  *   CPP id
3676d03aa61SChaoyong He  * @param address
3686d03aa61SChaoyong He  *   Address of region
3696d03aa61SChaoyong He  * @param size
3706d03aa61SChaoyong He  *   Size of region
3716d03aa61SChaoyong He  *
3726d03aa61SChaoyong He  * @return
3736d03aa61SChaoyong He  *   NFP CPP area handle, or NULL
3746d03aa61SChaoyong He  *
3756d03aa61SChaoyong He  * NOTE: @address and @size must be 32-bit aligned values.
3766d03aa61SChaoyong He  */
377c7e9729dSAlejandro Lucero struct nfp_cpp_area *
378d108b9e9SChaoyong He nfp_cpp_area_alloc(struct nfp_cpp *cpp,
379d108b9e9SChaoyong He 		uint32_t dest,
380c69debceSChaoyong He 		uint64_t address,
381c69debceSChaoyong He 		size_t size)
382c7e9729dSAlejandro Lucero {
383c7e9729dSAlejandro Lucero 	return nfp_cpp_area_alloc_with_name(cpp, dest, NULL, address, size);
384c7e9729dSAlejandro Lucero }
385c7e9729dSAlejandro Lucero 
3866d03aa61SChaoyong He /**
3877be78d02SJosh Soref  * Allocate and initialize a CPP area structure, and lock it down so
388c7e9729dSAlejandro Lucero  * that it can be accessed directly.
389c7e9729dSAlejandro Lucero  *
3906d03aa61SChaoyong He  * @param cpp
3916d03aa61SChaoyong He  *   CPP device handle
3926d03aa61SChaoyong He  * @param destination
3936d03aa61SChaoyong He  *   CPP id
3946d03aa61SChaoyong He  * @param address
3956d03aa61SChaoyong He  *   Address of region
3966d03aa61SChaoyong He  * @param size
3976d03aa61SChaoyong He  *   Size of region
3986d03aa61SChaoyong He  *
3996d03aa61SChaoyong He  * @return
4006d03aa61SChaoyong He  *   NFP CPP area handle, or NULL
4016d03aa61SChaoyong He  *
402c7e9729dSAlejandro Lucero  * NOTE: @address and @size must be 32-bit aligned values.
403c7e9729dSAlejandro Lucero  *
404c7e9729dSAlejandro Lucero  * NOTE: The area must also be 'released' when the structure is freed.
405c7e9729dSAlejandro Lucero  */
406c7e9729dSAlejandro Lucero struct nfp_cpp_area *
407d108b9e9SChaoyong He nfp_cpp_area_alloc_acquire(struct nfp_cpp *cpp,
408d108b9e9SChaoyong He 		uint32_t destination,
409c69debceSChaoyong He 		uint64_t address,
410c69debceSChaoyong He 		size_t size)
411c7e9729dSAlejandro Lucero {
412c7e9729dSAlejandro Lucero 	struct nfp_cpp_area *area;
413c7e9729dSAlejandro Lucero 
414c7e9729dSAlejandro Lucero 	area = nfp_cpp_area_alloc(cpp, destination, address, size);
415efa766e1SChaoyong He 	if (area == NULL) {
416*b6de4353SZerun Fu 		PMD_DRV_LOG(ERR, "Failed to allocate CPP area.");
417c7e9729dSAlejandro Lucero 		return NULL;
418efa766e1SChaoyong He 	}
419c7e9729dSAlejandro Lucero 
4204aa75cadSChaoyong He 	if (nfp_cpp_area_acquire(area) != 0) {
421*b6de4353SZerun Fu 		PMD_DRV_LOG(ERR, "Failed to acquire CPP area.");
422c7e9729dSAlejandro Lucero 		nfp_cpp_area_free(area);
423c7e9729dSAlejandro Lucero 		return NULL;
424c7e9729dSAlejandro Lucero 	}
425c7e9729dSAlejandro Lucero 
426c7e9729dSAlejandro Lucero 	return area;
427c7e9729dSAlejandro Lucero }
428c7e9729dSAlejandro Lucero 
4296d03aa61SChaoyong He /**
430c7e9729dSAlejandro Lucero  * Frees up memory resources held by the CPP area.
4316d03aa61SChaoyong He  *
4326d03aa61SChaoyong He  * @param area
4336d03aa61SChaoyong He  *   CPP area handle
434c7e9729dSAlejandro Lucero  */
435c7e9729dSAlejandro Lucero void
436c7e9729dSAlejandro Lucero nfp_cpp_area_free(struct nfp_cpp_area *area)
437c7e9729dSAlejandro Lucero {
4384aa75cadSChaoyong He 	if (area->cpp->op->area_cleanup != NULL)
439c7e9729dSAlejandro Lucero 		area->cpp->op->area_cleanup(area);
440c7e9729dSAlejandro Lucero 	free(area);
441c7e9729dSAlejandro Lucero }
442c7e9729dSAlejandro Lucero 
4436d03aa61SChaoyong He /**
4446d03aa61SChaoyong He  * Releases CPP area and frees up memory resources held by it.
445c7e9729dSAlejandro Lucero  *
4466d03aa61SChaoyong He  * @param area
4476d03aa61SChaoyong He  *   CPP area handle
448c7e9729dSAlejandro Lucero  */
449c7e9729dSAlejandro Lucero void
450c7e9729dSAlejandro Lucero nfp_cpp_area_release_free(struct nfp_cpp_area *area)
451c7e9729dSAlejandro Lucero {
452c7e9729dSAlejandro Lucero 	nfp_cpp_area_release(area);
453c7e9729dSAlejandro Lucero 	nfp_cpp_area_free(area);
454c7e9729dSAlejandro Lucero }
455c7e9729dSAlejandro Lucero 
4566d03aa61SChaoyong He /**
4576d03aa61SChaoyong He  * Locks down the CPP area for a potential long term activity.
4586d03aa61SChaoyong He  * Area must always be locked down before being accessed.
459c7e9729dSAlejandro Lucero  *
4606d03aa61SChaoyong He  * @param area
4616d03aa61SChaoyong He  *   CPP area handle
4626d03aa61SChaoyong He  *
4636d03aa61SChaoyong He  * @return
4646d03aa61SChaoyong He  *   0 on success, -1 on failure.
465c7e9729dSAlejandro Lucero  */
466c7e9729dSAlejandro Lucero int
467c7e9729dSAlejandro Lucero nfp_cpp_area_acquire(struct nfp_cpp_area *area)
468c7e9729dSAlejandro Lucero {
4694aa75cadSChaoyong He 	if (area->cpp->op->area_acquire != NULL) {
470c7e9729dSAlejandro Lucero 		int err = area->cpp->op->area_acquire(area);
471efa766e1SChaoyong He 		if (err < 0) {
472*b6de4353SZerun Fu 			PMD_DRV_LOG(ERR, "Area acquire op failed.");
473c7e9729dSAlejandro Lucero 			return -1;
474c7e9729dSAlejandro Lucero 		}
475efa766e1SChaoyong He 	}
476c7e9729dSAlejandro Lucero 
477c7e9729dSAlejandro Lucero 	return 0;
478c7e9729dSAlejandro Lucero }
479c7e9729dSAlejandro Lucero 
4806d03aa61SChaoyong He /**
481c7e9729dSAlejandro Lucero  * Releases a previously locked down CPP area.
4826d03aa61SChaoyong He  *
4836d03aa61SChaoyong He  * @param area
4846d03aa61SChaoyong He  *   CPP area handle
485c7e9729dSAlejandro Lucero  */
486c7e9729dSAlejandro Lucero void
487c7e9729dSAlejandro Lucero nfp_cpp_area_release(struct nfp_cpp_area *area)
488c7e9729dSAlejandro Lucero {
4894aa75cadSChaoyong He 	if (area->cpp->op->area_release != NULL)
490c7e9729dSAlejandro Lucero 		area->cpp->op->area_release(area);
491c7e9729dSAlejandro Lucero }
492c7e9729dSAlejandro Lucero 
4936d03aa61SChaoyong He /**
494c7e9729dSAlejandro Lucero  * Returns an iomem pointer for use with readl()/writel() style operations.
495c7e9729dSAlejandro Lucero  *
4966d03aa61SChaoyong He  * @param area
4976d03aa61SChaoyong He  *   CPP area handle
498c7e9729dSAlejandro Lucero  *
4996d03aa61SChaoyong He  * @return
5006d03aa61SChaoyong He  *   Pointer to the area, or NULL
5016d03aa61SChaoyong He  *
5026d03aa61SChaoyong He  * NOTE: Area must have been locked down with an 'acquire'.
503c7e9729dSAlejandro Lucero  */
504c7e9729dSAlejandro Lucero void *
505c7e9729dSAlejandro Lucero nfp_cpp_area_iomem(struct nfp_cpp_area *area)
506c7e9729dSAlejandro Lucero {
507c7e9729dSAlejandro Lucero 	void *iomem = NULL;
508c7e9729dSAlejandro Lucero 
5094aa75cadSChaoyong He 	if (area->cpp->op->area_iomem != NULL)
510c7e9729dSAlejandro Lucero 		iomem = area->cpp->op->area_iomem(area);
511c7e9729dSAlejandro Lucero 
512c7e9729dSAlejandro Lucero 	return iomem;
513c7e9729dSAlejandro Lucero }
514c7e9729dSAlejandro Lucero 
5156d03aa61SChaoyong He /**
516c7e9729dSAlejandro Lucero  * Read data from indicated CPP region.
517c7e9729dSAlejandro Lucero  *
5186d03aa61SChaoyong He  * @param area
5196d03aa61SChaoyong He  *   CPP area handle
5206d03aa61SChaoyong He  * @param offset
5216d03aa61SChaoyong He  *   Offset into CPP area
522588c5b10SChaoyong He  * @param address
5236d03aa61SChaoyong He  *   Address to put data into
5246d03aa61SChaoyong He  * @param length
5256d03aa61SChaoyong He  *   Number of bytes to read
526c7e9729dSAlejandro Lucero  *
5276d03aa61SChaoyong He  * @return
5286d03aa61SChaoyong He  *   Length of io, or -ERRNO
5296d03aa61SChaoyong He  *
5306d03aa61SChaoyong He  * NOTE: @offset and @length must be 32-bit aligned values.
531c7e9729dSAlejandro Lucero  * NOTE: Area must have been locked down with an 'acquire'.
532c7e9729dSAlejandro Lucero  */
533c7e9729dSAlejandro Lucero int
534d108b9e9SChaoyong He nfp_cpp_area_read(struct nfp_cpp_area *area,
535c69debceSChaoyong He 		uint32_t offset,
536588c5b10SChaoyong He 		void *address,
537d108b9e9SChaoyong He 		size_t length)
538c7e9729dSAlejandro Lucero {
539c7e9729dSAlejandro Lucero 	if ((offset + length) > area->size)
540b29d5df4SChaoyong He 		return -EFAULT;
541c7e9729dSAlejandro Lucero 
542588c5b10SChaoyong He 	return area->cpp->op->area_read(area, address, offset, length);
543c7e9729dSAlejandro Lucero }
544c7e9729dSAlejandro Lucero 
5456d03aa61SChaoyong He /**
546c7e9729dSAlejandro Lucero  * Write data to indicated CPP region.
547c7e9729dSAlejandro Lucero  *
5486d03aa61SChaoyong He  * @param area
5496d03aa61SChaoyong He  *   CPP area handle
5506d03aa61SChaoyong He  * @param offset
5516d03aa61SChaoyong He  *   Offset into CPP area
552588c5b10SChaoyong He  * @param address
5536d03aa61SChaoyong He  *   Address to put data into
5546d03aa61SChaoyong He  * @param length
5556d03aa61SChaoyong He  *   Number of bytes to read
556c7e9729dSAlejandro Lucero  *
5576d03aa61SChaoyong He  * @return
5586d03aa61SChaoyong He  *   Length of io, or -ERRNO
5596d03aa61SChaoyong He  *
5606d03aa61SChaoyong He  * NOTE: @offset and @length must be 32-bit aligned values.
561c7e9729dSAlejandro Lucero  * NOTE: Area must have been locked down with an 'acquire'.
562c7e9729dSAlejandro Lucero  */
563c7e9729dSAlejandro Lucero int
564d108b9e9SChaoyong He nfp_cpp_area_write(struct nfp_cpp_area *area,
565c69debceSChaoyong He 		uint32_t offset,
566588c5b10SChaoyong He 		const void *address,
567d108b9e9SChaoyong He 		size_t length)
568c7e9729dSAlejandro Lucero {
569c7e9729dSAlejandro Lucero 	if ((offset + length) > area->size)
570b29d5df4SChaoyong He 		return -EFAULT;
571c7e9729dSAlejandro Lucero 
572588c5b10SChaoyong He 	return area->cpp->op->area_write(area, address, offset, length);
573c7e9729dSAlejandro Lucero }
574c7e9729dSAlejandro Lucero 
575c7e9729dSAlejandro Lucero /*
576c7e9729dSAlejandro Lucero  * Return the correct CPP address, and fixup xpb_addr as needed,
577c7e9729dSAlejandro Lucero  * based upon NFP model.
578c7e9729dSAlejandro Lucero  */
579c7e9729dSAlejandro Lucero static uint32_t
580d108b9e9SChaoyong He nfp_xpb_to_cpp(struct nfp_cpp *cpp,
581d108b9e9SChaoyong He 		uint32_t *xpb_addr)
582c7e9729dSAlejandro Lucero {
583c7e9729dSAlejandro Lucero 	int island;
584610bf14bSChaoyong He 	uint32_t xpb;
585c7e9729dSAlejandro Lucero 
586c7e9729dSAlejandro Lucero 	xpb = NFP_CPP_ID(14, NFP_CPP_ACTION_RW, 0);
587c7e9729dSAlejandro Lucero 
588c7e9729dSAlejandro Lucero 	/*
589c7e9729dSAlejandro Lucero 	 * Ensure that non-local XPB accesses go out through the
590c7e9729dSAlejandro Lucero 	 * global XPBM bus.
591c7e9729dSAlejandro Lucero 	 */
592ff627b74SChaoyong He 	island = (*xpb_addr >> 24) & 0x3f;
593c7e9729dSAlejandro Lucero 
594cbcbfd73SJames Hershaw 	if (island == 0)
595c7e9729dSAlejandro Lucero 		return xpb;
596c7e9729dSAlejandro Lucero 
597ff627b74SChaoyong He 	if (island != 1) {
598ff627b74SChaoyong He 		*xpb_addr |= (1 << 30);
599ff627b74SChaoyong He 		return xpb;
600ff627b74SChaoyong He 	}
601ff627b74SChaoyong He 
602c7e9729dSAlejandro Lucero 	/*
603c7e9729dSAlejandro Lucero 	 * Accesses to the ARM Island overlay uses Island 0
604c7e9729dSAlejandro Lucero 	 * Global Bit
605c7e9729dSAlejandro Lucero 	 */
606ff627b74SChaoyong He 	*xpb_addr &= ~0x7f000000;
607ff627b74SChaoyong He 	if (*xpb_addr < 0x60000) {
608c7e9729dSAlejandro Lucero 		*xpb_addr |= (1 << 30);
609ff627b74SChaoyong He 	} else {
610c7e9729dSAlejandro Lucero 		/* And only non-ARM interfaces use island id = 1 */
611c7e9729dSAlejandro Lucero 		if (NFP_CPP_INTERFACE_TYPE_of(nfp_cpp_interface(cpp)) !=
612c7e9729dSAlejandro Lucero 				NFP_CPP_INTERFACE_TYPE_ARM)
613c7e9729dSAlejandro Lucero 			*xpb_addr |= (1 << 24);
614c7e9729dSAlejandro Lucero 	}
615c7e9729dSAlejandro Lucero 
616c7e9729dSAlejandro Lucero 	return xpb;
617c7e9729dSAlejandro Lucero }
618c7e9729dSAlejandro Lucero 
6196d03aa61SChaoyong He /**
6206d03aa61SChaoyong He  * Read a uint32_t value from an area
6216d03aa61SChaoyong He  *
6226d03aa61SChaoyong He  * @param area
6236d03aa61SChaoyong He  *   CPP Area handle
6246d03aa61SChaoyong He  * @param offset
6256d03aa61SChaoyong He  *   Offset into area
6266d03aa61SChaoyong He  * @param value
6276d03aa61SChaoyong He  *   Pointer to read buffer
6286d03aa61SChaoyong He  *
6296d03aa61SChaoyong He  * @return
6306d03aa61SChaoyong He  *   0 on success, or -ERRNO
6316d03aa61SChaoyong He  */
632c7e9729dSAlejandro Lucero int
633d108b9e9SChaoyong He nfp_cpp_area_readl(struct nfp_cpp_area *area,
634c69debceSChaoyong He 		uint32_t offset,
635c7e9729dSAlejandro Lucero 		uint32_t *value)
636c7e9729dSAlejandro Lucero {
637c7e9729dSAlejandro Lucero 	int sz;
638c7e9729dSAlejandro Lucero 	uint32_t tmp = 0;
639c7e9729dSAlejandro Lucero 
640c7e9729dSAlejandro Lucero 	sz = nfp_cpp_area_read(area, offset, &tmp, sizeof(tmp));
641ff627b74SChaoyong He 	if (sz != sizeof(tmp))
642ff627b74SChaoyong He 		return sz < 0 ? sz : -EIO;
643ff627b74SChaoyong He 
644c7e9729dSAlejandro Lucero 	*value = rte_le_to_cpu_32(tmp);
645c7e9729dSAlejandro Lucero 
646ff627b74SChaoyong He 	return 0;
647c7e9729dSAlejandro Lucero }
648c7e9729dSAlejandro Lucero 
6496d03aa61SChaoyong He /**
6506d03aa61SChaoyong He  * Write a uint32_t vale to an area
6516d03aa61SChaoyong He  *
6526d03aa61SChaoyong He  * @param area
6536d03aa61SChaoyong He  *   CPP Area handle
6546d03aa61SChaoyong He  * @param offset
6556d03aa61SChaoyong He  *   Offset into area
6566d03aa61SChaoyong He  * @param value
6576d03aa61SChaoyong He  *   Value to write
6586d03aa61SChaoyong He  *
6596d03aa61SChaoyong He  * @return
6606d03aa61SChaoyong He  *   0 on success, or -ERRNO
6616d03aa61SChaoyong He  */
662c7e9729dSAlejandro Lucero int
663d108b9e9SChaoyong He nfp_cpp_area_writel(struct nfp_cpp_area *area,
664c69debceSChaoyong He 		uint32_t offset,
665c7e9729dSAlejandro Lucero 		uint32_t value)
666c7e9729dSAlejandro Lucero {
667c7e9729dSAlejandro Lucero 	int sz;
668c7e9729dSAlejandro Lucero 
669c7e9729dSAlejandro Lucero 	value = rte_cpu_to_le_32(value);
670c7e9729dSAlejandro Lucero 	sz = nfp_cpp_area_write(area, offset, &value, sizeof(value));
671ff627b74SChaoyong He 	if (sz != sizeof(value))
672ff627b74SChaoyong He 		return sz < 0 ? sz : -EIO;
673ff627b74SChaoyong He 
674ff627b74SChaoyong He 	return 0;
675c7e9729dSAlejandro Lucero }
676c7e9729dSAlejandro Lucero 
6776d03aa61SChaoyong He /**
6786d03aa61SChaoyong He  * Read a uint64_t value from an area
6796d03aa61SChaoyong He  *
6806d03aa61SChaoyong He  * @param area
6816d03aa61SChaoyong He  *   CPP Area handle
6826d03aa61SChaoyong He  * @param offset
6836d03aa61SChaoyong He  *   Offset into area
6846d03aa61SChaoyong He  * @param value
6856d03aa61SChaoyong He  *   Pointer to read buffer
6866d03aa61SChaoyong He  *
6876d03aa61SChaoyong He  * @return
6886d03aa61SChaoyong He  *   0 on success, or -ERRNO
6896d03aa61SChaoyong He  */
690c7e9729dSAlejandro Lucero int
691d108b9e9SChaoyong He nfp_cpp_area_readq(struct nfp_cpp_area *area,
692c69debceSChaoyong He 		uint32_t offset,
693c7e9729dSAlejandro Lucero 		uint64_t *value)
694c7e9729dSAlejandro Lucero {
695c7e9729dSAlejandro Lucero 	int sz;
696c7e9729dSAlejandro Lucero 	uint64_t tmp = 0;
697c7e9729dSAlejandro Lucero 
698c7e9729dSAlejandro Lucero 	sz = nfp_cpp_area_read(area, offset, &tmp, sizeof(tmp));
699ff627b74SChaoyong He 	if (sz != sizeof(tmp))
700ff627b74SChaoyong He 		return sz < 0 ? sz : -EIO;
701ff627b74SChaoyong He 
702c7e9729dSAlejandro Lucero 	*value = rte_le_to_cpu_64(tmp);
703c7e9729dSAlejandro Lucero 
704ff627b74SChaoyong He 	return 0;
705c7e9729dSAlejandro Lucero }
706c7e9729dSAlejandro Lucero 
7076d03aa61SChaoyong He /**
7086d03aa61SChaoyong He  * Write a uint64_t vale to an area
7096d03aa61SChaoyong He  *
7106d03aa61SChaoyong He  * @param area
7116d03aa61SChaoyong He  *   CPP Area handle
7126d03aa61SChaoyong He  * @param offset
7136d03aa61SChaoyong He  *   Offset into area
7146d03aa61SChaoyong He  * @param value
7156d03aa61SChaoyong He  *   Value to write
7166d03aa61SChaoyong He  *
7176d03aa61SChaoyong He  * @return
7186d03aa61SChaoyong He  *   0 on success, or -ERRNO
7196d03aa61SChaoyong He  */
720c7e9729dSAlejandro Lucero int
721d108b9e9SChaoyong He nfp_cpp_area_writeq(struct nfp_cpp_area *area,
722c69debceSChaoyong He 		uint32_t offset,
723c7e9729dSAlejandro Lucero 		uint64_t value)
724c7e9729dSAlejandro Lucero {
725c7e9729dSAlejandro Lucero 	int sz;
726c7e9729dSAlejandro Lucero 
727c7e9729dSAlejandro Lucero 	value = rte_cpu_to_le_64(value);
728c7e9729dSAlejandro Lucero 	sz = nfp_cpp_area_write(area, offset, &value, sizeof(value));
729ff627b74SChaoyong He 	if (sz != sizeof(value))
730ff627b74SChaoyong He 		return sz < 0 ? sz : -EIO;
731c7e9729dSAlejandro Lucero 
732ff627b74SChaoyong He 	return 0;
733c7e9729dSAlejandro Lucero }
734c7e9729dSAlejandro Lucero 
7356d03aa61SChaoyong He /**
7366d03aa61SChaoyong He  * Read a uint32_t value from a CPP location
7376d03aa61SChaoyong He  *
7386d03aa61SChaoyong He  * @param cpp
7396d03aa61SChaoyong He  *   CPP device handle
7406d03aa61SChaoyong He  * @param cpp_id
7416d03aa61SChaoyong He  *   CPP ID for operation
7426d03aa61SChaoyong He  * @param address
7436d03aa61SChaoyong He  *   Address for operation
7446d03aa61SChaoyong He  * @param value
7456d03aa61SChaoyong He  *   Pointer to read buffer
7466d03aa61SChaoyong He  *
7476d03aa61SChaoyong He  * @return
7486d03aa61SChaoyong He  *   0 on success, or -ERRNO
7496d03aa61SChaoyong He  */
750c7e9729dSAlejandro Lucero int
751d108b9e9SChaoyong He nfp_cpp_readl(struct nfp_cpp *cpp,
752d108b9e9SChaoyong He 		uint32_t cpp_id,
753c69debceSChaoyong He 		uint64_t address,
754c7e9729dSAlejandro Lucero 		uint32_t *value)
755c7e9729dSAlejandro Lucero {
756c7e9729dSAlejandro Lucero 	int sz;
757c7e9729dSAlejandro Lucero 	uint32_t tmp;
758c7e9729dSAlejandro Lucero 
759c7e9729dSAlejandro Lucero 	sz = nfp_cpp_read(cpp, cpp_id, address, &tmp, sizeof(tmp));
760ff627b74SChaoyong He 	if (sz != sizeof(tmp))
761ff627b74SChaoyong He 		return sz < 0 ? sz : -EIO;
762ff627b74SChaoyong He 
763c7e9729dSAlejandro Lucero 	*value = rte_le_to_cpu_32(tmp);
764c7e9729dSAlejandro Lucero 
765ff627b74SChaoyong He 	return 0;
766c7e9729dSAlejandro Lucero }
767c7e9729dSAlejandro Lucero 
7686d03aa61SChaoyong He /**
7696d03aa61SChaoyong He  * Write a uint32_t value to a CPP location
7706d03aa61SChaoyong He  *
7716d03aa61SChaoyong He  * @param cpp
7726d03aa61SChaoyong He  *   CPP device handle
7736d03aa61SChaoyong He  * @param cpp_id
7746d03aa61SChaoyong He  *   CPP ID for operation
7756d03aa61SChaoyong He  * @param address
7766d03aa61SChaoyong He  *   Address for operation
7776d03aa61SChaoyong He  * @param value
7786d03aa61SChaoyong He  *   Value to write
7796d03aa61SChaoyong He  *
7806d03aa61SChaoyong He  * @return
7816d03aa61SChaoyong He  *   0 on success, or -ERRNO
7826d03aa61SChaoyong He  */
783c7e9729dSAlejandro Lucero int
784d108b9e9SChaoyong He nfp_cpp_writel(struct nfp_cpp *cpp,
785d108b9e9SChaoyong He 		uint32_t cpp_id,
786c69debceSChaoyong He 		uint64_t address,
787c7e9729dSAlejandro Lucero 		uint32_t value)
788c7e9729dSAlejandro Lucero {
789c7e9729dSAlejandro Lucero 	int sz;
790c7e9729dSAlejandro Lucero 
791c7e9729dSAlejandro Lucero 	value = rte_cpu_to_le_32(value);
792c7e9729dSAlejandro Lucero 	sz = nfp_cpp_write(cpp, cpp_id, address, &value, sizeof(value));
793ff627b74SChaoyong He 	if (sz != sizeof(value))
794ff627b74SChaoyong He 		return sz < 0 ? sz : -EIO;
795c7e9729dSAlejandro Lucero 
796ff627b74SChaoyong He 	return 0;
797c7e9729dSAlejandro Lucero }
798c7e9729dSAlejandro Lucero 
7996d03aa61SChaoyong He /**
8006d03aa61SChaoyong He  * Read a uint64_t value from a CPP location
8016d03aa61SChaoyong He  *
8026d03aa61SChaoyong He  * @param cpp
8036d03aa61SChaoyong He  *   CPP device handle
8046d03aa61SChaoyong He  * @param cpp_id
8056d03aa61SChaoyong He  *   CPP ID for operation
8066d03aa61SChaoyong He  * @param address
8076d03aa61SChaoyong He  *   Address for operation
8086d03aa61SChaoyong He  * @param value
8096d03aa61SChaoyong He  *   Pointer to read buffer
8106d03aa61SChaoyong He  *
8116d03aa61SChaoyong He  * @return
8126d03aa61SChaoyong He  *   0 on success, or -ERRNO
8136d03aa61SChaoyong He  */
814c7e9729dSAlejandro Lucero int
815d108b9e9SChaoyong He nfp_cpp_readq(struct nfp_cpp *cpp,
816d108b9e9SChaoyong He 		uint32_t cpp_id,
817c69debceSChaoyong He 		uint64_t address,
818c7e9729dSAlejandro Lucero 		uint64_t *value)
819c7e9729dSAlejandro Lucero {
820c7e9729dSAlejandro Lucero 	int sz;
821c7e9729dSAlejandro Lucero 	uint64_t tmp;
822c7e9729dSAlejandro Lucero 
823c7e9729dSAlejandro Lucero 	sz = nfp_cpp_read(cpp, cpp_id, address, &tmp, sizeof(tmp));
824c7e9729dSAlejandro Lucero 	*value = rte_le_to_cpu_64(tmp);
825ff627b74SChaoyong He 	if (sz != sizeof(tmp))
826ff627b74SChaoyong He 		return sz < 0 ? sz : -EIO;
827c7e9729dSAlejandro Lucero 
828ff627b74SChaoyong He 	return 0;
829c7e9729dSAlejandro Lucero }
830c7e9729dSAlejandro Lucero 
8316d03aa61SChaoyong He /**
8326d03aa61SChaoyong He  * Write a uint64_t value to a CPP location
8336d03aa61SChaoyong He  *
8346d03aa61SChaoyong He  * @param cpp
8356d03aa61SChaoyong He  *   CPP device handle
8366d03aa61SChaoyong He  * @param cpp_id
8376d03aa61SChaoyong He  *   CPP ID for operation
8386d03aa61SChaoyong He  * @param address
8396d03aa61SChaoyong He  *   Address for operation
8406d03aa61SChaoyong He  * @param value
8416d03aa61SChaoyong He  *   Value to write
8426d03aa61SChaoyong He  *
8436d03aa61SChaoyong He  * @return
8446d03aa61SChaoyong He  *   0 on success, or -ERRNO
8456d03aa61SChaoyong He  */
846c7e9729dSAlejandro Lucero int
847d108b9e9SChaoyong He nfp_cpp_writeq(struct nfp_cpp *cpp,
848d108b9e9SChaoyong He 		uint32_t cpp_id,
849c69debceSChaoyong He 		uint64_t address,
850c7e9729dSAlejandro Lucero 		uint64_t value)
851c7e9729dSAlejandro Lucero {
852c7e9729dSAlejandro Lucero 	int sz;
853c7e9729dSAlejandro Lucero 
854c7e9729dSAlejandro Lucero 	value = rte_cpu_to_le_64(value);
855c7e9729dSAlejandro Lucero 	sz = nfp_cpp_write(cpp, cpp_id, address, &value, sizeof(value));
856ff627b74SChaoyong He 	if (sz != sizeof(value))
857ff627b74SChaoyong He 		return sz < 0 ? sz : -EIO;
858c7e9729dSAlejandro Lucero 
859ff627b74SChaoyong He 	return 0;
860c7e9729dSAlejandro Lucero }
861c7e9729dSAlejandro Lucero 
8626d03aa61SChaoyong He /**
8636d03aa61SChaoyong He  * Write a uint32_t word to a XPB location
8646d03aa61SChaoyong He  *
8656d03aa61SChaoyong He  * @param cpp
8666d03aa61SChaoyong He  *   CPP device handle
8676d03aa61SChaoyong He  * @param xpb_addr
8686d03aa61SChaoyong He  *   XPB target and address
8696d03aa61SChaoyong He  * @param value
8706d03aa61SChaoyong He  *   Value to write
8716d03aa61SChaoyong He  *
8726d03aa61SChaoyong He  * @return
8736d03aa61SChaoyong He  *   0 on success, or -ERRNO
8746d03aa61SChaoyong He  */
875c7e9729dSAlejandro Lucero int
876d108b9e9SChaoyong He nfp_xpb_writel(struct nfp_cpp *cpp,
877d108b9e9SChaoyong He 		uint32_t xpb_addr,
878d108b9e9SChaoyong He 		uint32_t value)
879c7e9729dSAlejandro Lucero {
880c7e9729dSAlejandro Lucero 	uint32_t cpp_dest;
881c7e9729dSAlejandro Lucero 
882c7e9729dSAlejandro Lucero 	cpp_dest = nfp_xpb_to_cpp(cpp, &xpb_addr);
883c7e9729dSAlejandro Lucero 
884c7e9729dSAlejandro Lucero 	return nfp_cpp_writel(cpp, cpp_dest, xpb_addr, value);
885c7e9729dSAlejandro Lucero }
886c7e9729dSAlejandro Lucero 
8876d03aa61SChaoyong He /**
8886d03aa61SChaoyong He  * Read a uint32_t value from a XPB location
8896d03aa61SChaoyong He  *
8906d03aa61SChaoyong He  * @param cpp
8916d03aa61SChaoyong He  *   CPP device handle
8926d03aa61SChaoyong He  * @param xpb_addr
8936d03aa61SChaoyong He  *   XPB target and address
8946d03aa61SChaoyong He  * @param value
8956d03aa61SChaoyong He  *   Pointer to read buffer
8966d03aa61SChaoyong He  *
8976d03aa61SChaoyong He  * @return
8986d03aa61SChaoyong He  *   0 on success, or -ERRNO
8996d03aa61SChaoyong He  */
900c7e9729dSAlejandro Lucero int
901d108b9e9SChaoyong He nfp_xpb_readl(struct nfp_cpp *cpp,
902d108b9e9SChaoyong He 		uint32_t xpb_addr,
903d108b9e9SChaoyong He 		uint32_t *value)
904c7e9729dSAlejandro Lucero {
905c7e9729dSAlejandro Lucero 	uint32_t cpp_dest;
906c7e9729dSAlejandro Lucero 
907c7e9729dSAlejandro Lucero 	cpp_dest = nfp_xpb_to_cpp(cpp, &xpb_addr);
908c7e9729dSAlejandro Lucero 
909c7e9729dSAlejandro Lucero 	return nfp_cpp_readl(cpp, cpp_dest, xpb_addr, value);
910c7e9729dSAlejandro Lucero }
911c7e9729dSAlejandro Lucero 
912c7e9729dSAlejandro Lucero static struct nfp_cpp *
913796f1aecSChaoyong He nfp_cpp_alloc(struct rte_pci_device *pci_dev,
914796f1aecSChaoyong He 		void *priv,
915796f1aecSChaoyong He 		bool driver_lock_needed)
916c7e9729dSAlejandro Lucero {
917c7e9729dSAlejandro Lucero 	int err;
918796f1aecSChaoyong He 	size_t target;
919796f1aecSChaoyong He 	uint32_t xpb_addr;
920610bf14bSChaoyong He 	struct nfp_cpp *cpp;
921610bf14bSChaoyong He 	const struct nfp_cpp_operations *ops;
922c7e9729dSAlejandro Lucero 
923c7e9729dSAlejandro Lucero 	ops = nfp_cpp_transport_operations();
924cbcbfd73SJames Hershaw 	if (ops == NULL || ops->init == NULL)
925b29d5df4SChaoyong He 		return NULL;
926c7e9729dSAlejandro Lucero 
927c7e9729dSAlejandro Lucero 	cpp = calloc(1, sizeof(*cpp));
928cbcbfd73SJames Hershaw 	if (cpp == NULL)
929c7e9729dSAlejandro Lucero 		return NULL;
930c7e9729dSAlejandro Lucero 
931c7e9729dSAlejandro Lucero 	cpp->op = ops;
932796f1aecSChaoyong He 	cpp->priv = priv;
9335f6ed2f4SAlejandro Lucero 	cpp->driver_lock_needed = driver_lock_needed;
934c7e9729dSAlejandro Lucero 
935796f1aecSChaoyong He 	err = ops->get_interface(pci_dev, &cpp->interface);
936796f1aecSChaoyong He 	if (err != 0) {
937c7e9729dSAlejandro Lucero 		free(cpp);
938c7e9729dSAlejandro Lucero 		return NULL;
939c7e9729dSAlejandro Lucero 	}
940796f1aecSChaoyong He 
941796f1aecSChaoyong He 	err = ops->get_serial(pci_dev, cpp->serial, NFP_SERIAL_LEN);
942796f1aecSChaoyong He 	if (err != 0) {
943796f1aecSChaoyong He 		free(cpp);
944796f1aecSChaoyong He 		return NULL;
945c7e9729dSAlejandro Lucero 	}
946c7e9729dSAlejandro Lucero 
947796f1aecSChaoyong He 	/*
948796f1aecSChaoyong He 	 * NOTE: cpp_lock is NOT locked for op->init,
949796f1aecSChaoyong He 	 * since it may call NFP CPP API operations
950796f1aecSChaoyong He 	 */
9511fbe51cdSChaoyong He 	err = cpp->op->init(cpp);
952796f1aecSChaoyong He 	if (err < 0) {
953*b6de4353SZerun Fu 		PMD_DRV_LOG(ERR, "NFP interface initialization failed.");
954796f1aecSChaoyong He 		free(cpp);
955796f1aecSChaoyong He 		return NULL;
956796f1aecSChaoyong He 	}
957796f1aecSChaoyong He 
958796f1aecSChaoyong He 	err = nfp_cpp_model_autodetect(cpp, &cpp->model);
959796f1aecSChaoyong He 	if (err < 0) {
960*b6de4353SZerun Fu 		PMD_DRV_LOG(ERR, "NFP model detection failed.");
961796f1aecSChaoyong He 		free(cpp);
962796f1aecSChaoyong He 		return NULL;
963796f1aecSChaoyong He 	}
964c7e9729dSAlejandro Lucero 
965588c5b10SChaoyong He 	for (target = 0; target < RTE_DIM(cpp->imb_cat_table); target++) {
966c7e9729dSAlejandro Lucero 		/* Hardcoded XPB IMB Base, island 0 */
967588c5b10SChaoyong He 		xpb_addr = 0x000a0000 + (target * 4);
968796f1aecSChaoyong He 		err = nfp_xpb_readl(cpp, xpb_addr, &cpp->imb_cat_table[target]);
969c7e9729dSAlejandro Lucero 		if (err < 0) {
970*b6de4353SZerun Fu 			PMD_DRV_LOG(ERR, "Can not read CPP mapping from device.");
971c7e9729dSAlejandro Lucero 			free(cpp);
972c7e9729dSAlejandro Lucero 			return NULL;
973c7e9729dSAlejandro Lucero 		}
974c7e9729dSAlejandro Lucero 	}
975c7e9729dSAlejandro Lucero 
976925c27ecSChaoyong He 	err = nfp_cpp_set_mu_locality_lsb(cpp);
977925c27ecSChaoyong He 	if (err < 0) {
978*b6de4353SZerun Fu 		PMD_DRV_LOG(ERR, "Can not calculate MU locality bit offset.");
979925c27ecSChaoyong He 		free(cpp);
980925c27ecSChaoyong He 		return NULL;
981925c27ecSChaoyong He 	}
982925c27ecSChaoyong He 
983c7e9729dSAlejandro Lucero 	return cpp;
984c7e9729dSAlejandro Lucero }
985c7e9729dSAlejandro Lucero 
9866d03aa61SChaoyong He /**
9876d03aa61SChaoyong He  * Free the CPP handle
9886d03aa61SChaoyong He  *
9896d03aa61SChaoyong He  * @param cpp
9906d03aa61SChaoyong He  *   CPP handle
991c7e9729dSAlejandro Lucero  */
992c7e9729dSAlejandro Lucero void
993c7e9729dSAlejandro Lucero nfp_cpp_free(struct nfp_cpp *cpp)
994c7e9729dSAlejandro Lucero {
9954aa75cadSChaoyong He 	if (cpp->op != NULL && cpp->op->free != NULL)
996c7e9729dSAlejandro Lucero 		cpp->op->free(cpp);
997c7e9729dSAlejandro Lucero 
998c7e9729dSAlejandro Lucero 	free(cpp);
999c7e9729dSAlejandro Lucero }
1000c7e9729dSAlejandro Lucero 
10016d03aa61SChaoyong He /**
10026d03aa61SChaoyong He  * Create a NFP CPP handle from device
10036d03aa61SChaoyong He  *
10046d03aa61SChaoyong He  * @param dev
10056d03aa61SChaoyong He  *   PCI device
1006796f1aecSChaoyong He  * @param priv
1007796f1aecSChaoyong He  *   Private data of low-level implementation
10086d03aa61SChaoyong He  * @param driver_lock_needed
10096d03aa61SChaoyong He  *   Driver lock flag
10106d03aa61SChaoyong He  *
10116d03aa61SChaoyong He  * @return
10126d03aa61SChaoyong He  *   NFP CPP handle on success, NULL on failure
10136d03aa61SChaoyong He  *
10146d03aa61SChaoyong He  * NOTE: On failure, cpp_ops->free will be called!
10156d03aa61SChaoyong He  */
1016c7e9729dSAlejandro Lucero struct nfp_cpp *
1017d108b9e9SChaoyong He nfp_cpp_from_device_name(struct rte_pci_device *dev,
1018796f1aecSChaoyong He 		void *priv,
1019796f1aecSChaoyong He 		bool driver_lock_needed)
1020c7e9729dSAlejandro Lucero {
1021796f1aecSChaoyong He 	return nfp_cpp_alloc(dev, priv, driver_lock_needed);
1022c7e9729dSAlejandro Lucero }
1023c7e9729dSAlejandro Lucero 
10246d03aa61SChaoyong He /**
10256d03aa61SChaoyong He  * Read from CPP target
10266d03aa61SChaoyong He  *
10276d03aa61SChaoyong He  * @param cpp
10286d03aa61SChaoyong He  *   CPP handle
10296d03aa61SChaoyong He  * @param destination
10306d03aa61SChaoyong He  *   CPP id
1031588c5b10SChaoyong He  * @param offset
10326d03aa61SChaoyong He  *   Offset into CPP target
1033588c5b10SChaoyong He  * @param address
10346d03aa61SChaoyong He  *   Buffer for result
10356d03aa61SChaoyong He  * @param length
10366d03aa61SChaoyong He  *   Number of bytes to read
10376d03aa61SChaoyong He  *
10386d03aa61SChaoyong He  * @return
10396d03aa61SChaoyong He  *   Length of io, or -ERRNO
1040c7e9729dSAlejandro Lucero  */
1041c7e9729dSAlejandro Lucero int
1042d108b9e9SChaoyong He nfp_cpp_read(struct nfp_cpp *cpp,
1043d108b9e9SChaoyong He 		uint32_t destination,
1044588c5b10SChaoyong He 		uint64_t offset,
1045588c5b10SChaoyong He 		void *address,
1046d108b9e9SChaoyong He 		size_t length)
1047c7e9729dSAlejandro Lucero {
1048c7e9729dSAlejandro Lucero 	int err;
1049610bf14bSChaoyong He 	struct nfp_cpp_area *area;
1050c7e9729dSAlejandro Lucero 
1051588c5b10SChaoyong He 	area = nfp_cpp_area_alloc_acquire(cpp, destination, offset, length);
1052cbcbfd73SJames Hershaw 	if (area == NULL) {
1053*b6de4353SZerun Fu 		PMD_DRV_LOG(ERR, "Area allocation/acquire failed for read.");
1054ff627b74SChaoyong He 		return -EACCES;
1055c7e9729dSAlejandro Lucero 	}
1056c7e9729dSAlejandro Lucero 
1057588c5b10SChaoyong He 	err = nfp_cpp_area_read(area, 0, address, length);
1058c7e9729dSAlejandro Lucero 
1059c7e9729dSAlejandro Lucero 	nfp_cpp_area_release_free(area);
1060c7e9729dSAlejandro Lucero 	return err;
1061c7e9729dSAlejandro Lucero }
1062c7e9729dSAlejandro Lucero 
10636d03aa61SChaoyong He /**
10646d03aa61SChaoyong He  * Write to CPP target
10656d03aa61SChaoyong He  *
10666d03aa61SChaoyong He  * @param cpp
10676d03aa61SChaoyong He  *   CPP handle
10686d03aa61SChaoyong He  * @param destination
10696d03aa61SChaoyong He  *   CPP id
1070588c5b10SChaoyong He  * @param offset
10716d03aa61SChaoyong He  *   Offset into CPP target
1072588c5b10SChaoyong He  * @param address
10736d03aa61SChaoyong He  *   Buffer to read from
10746d03aa61SChaoyong He  * @param length
10756d03aa61SChaoyong He  *   Number of bytes to write
10766d03aa61SChaoyong He  *
10776d03aa61SChaoyong He  * @return
10786d03aa61SChaoyong He  *   Length of io, or -ERRNO
1079c7e9729dSAlejandro Lucero  */
1080c7e9729dSAlejandro Lucero int
1081d108b9e9SChaoyong He nfp_cpp_write(struct nfp_cpp *cpp,
1082d108b9e9SChaoyong He 		uint32_t destination,
1083588c5b10SChaoyong He 		uint64_t offset,
1084588c5b10SChaoyong He 		const void *address,
1085c7e9729dSAlejandro Lucero 		size_t length)
1086c7e9729dSAlejandro Lucero {
1087c7e9729dSAlejandro Lucero 	int err;
1088610bf14bSChaoyong He 	struct nfp_cpp_area *area;
1089c7e9729dSAlejandro Lucero 
1090588c5b10SChaoyong He 	area = nfp_cpp_area_alloc_acquire(cpp, destination, offset, length);
1091efa766e1SChaoyong He 	if (area == NULL) {
1092*b6de4353SZerun Fu 		PMD_DRV_LOG(ERR, "Area allocation/acquire failed for write.");
1093ff627b74SChaoyong He 		return -EACCES;
1094efa766e1SChaoyong He 	}
1095c7e9729dSAlejandro Lucero 
1096588c5b10SChaoyong He 	err = nfp_cpp_area_write(area, 0, address, length);
1097c7e9729dSAlejandro Lucero 
1098c7e9729dSAlejandro Lucero 	nfp_cpp_area_release_free(area);
1099c7e9729dSAlejandro Lucero 	return err;
1100c7e9729dSAlejandro Lucero }
1101c7e9729dSAlejandro Lucero 
1102c7e9729dSAlejandro Lucero /*
1103c7e9729dSAlejandro Lucero  * NOTE: This code should not use nfp_xpb_* functions,
1104c7e9729dSAlejandro Lucero  * as those are model-specific
1105c7e9729dSAlejandro Lucero  */
1106c7e9729dSAlejandro Lucero uint32_t
1107588c5b10SChaoyong He nfp_cpp_model_autodetect(struct nfp_cpp *cpp,
1108d108b9e9SChaoyong He 		uint32_t *model)
1109c7e9729dSAlejandro Lucero {
1110c0a8b024SHeinrich Kuhn 	int err;
1111610bf14bSChaoyong He 	uint32_t reg;
1112c7e9729dSAlejandro Lucero 
1113c0a8b024SHeinrich Kuhn 	err = nfp_xpb_readl(cpp, NFP_XPB_DEVICE(1, 1, 16) + NFP_PL_DEVICE_ID,
1114c0a8b024SHeinrich Kuhn 			&reg);
1115c0a8b024SHeinrich Kuhn 	if (err < 0)
1116c0a8b024SHeinrich Kuhn 		return err;
1117c0a8b024SHeinrich Kuhn 
1118c0a8b024SHeinrich Kuhn 	*model = reg & NFP_PL_DEVICE_MODEL_MASK;
1119ff627b74SChaoyong He 	/* Disambiguate the NFP4000/NFP5000/NFP6000 chips */
1120ff627b74SChaoyong He 	if (FIELD_GET(NFP_PL_DEVICE_PART_MASK, reg) ==
1121ff627b74SChaoyong He 			NFP_PL_DEVICE_PART_NFP6000) {
11224aa75cadSChaoyong He 		if ((*model & NFP_PL_DEVICE_ID_MASK) != 0)
1123c0a8b024SHeinrich Kuhn 			*model -= 0x10;
1124ff627b74SChaoyong He 	}
1125c0a8b024SHeinrich Kuhn 
11260fec453dSAlejandro Lucero 	return 0;
1127c7e9729dSAlejandro Lucero }
1128c7e9729dSAlejandro Lucero 
11296d03aa61SChaoyong He /**
11306d03aa61SChaoyong He  * Map an area of IOMEM access.
11316d03aa61SChaoyong He  * To undo the effect of this function call @nfp_cpp_area_release_free(*area).
1132c7e9729dSAlejandro Lucero  *
11336d03aa61SChaoyong He  * @param cpp
11346d03aa61SChaoyong He  *   NFP CPP handler
11356d03aa61SChaoyong He  * @param cpp_id
11366d03aa61SChaoyong He  *   CPP id
11376d03aa61SChaoyong He  * @param addr
11386d03aa61SChaoyong He  *   CPP address
11396d03aa61SChaoyong He  * @param size
11406d03aa61SChaoyong He  *   Size of the area
11416d03aa61SChaoyong He  * @param area
11426d03aa61SChaoyong He  *   Area handle (output)
1143c7e9729dSAlejandro Lucero  *
11446d03aa61SChaoyong He  * @return
11456d03aa61SChaoyong He  *   Pointer to memory mapped area or NULL
1146c7e9729dSAlejandro Lucero  */
1147c7e9729dSAlejandro Lucero uint8_t *
1148d108b9e9SChaoyong He nfp_cpp_map_area(struct nfp_cpp *cpp,
1149d108b9e9SChaoyong He 		uint32_t cpp_id,
1150d108b9e9SChaoyong He 		uint64_t addr,
1151c69debceSChaoyong He 		uint32_t size,
1152d108b9e9SChaoyong He 		struct nfp_cpp_area **area)
1153c7e9729dSAlejandro Lucero {
1154c7e9729dSAlejandro Lucero 	uint8_t *res;
1155c7e9729dSAlejandro Lucero 
1156925c27ecSChaoyong He 	*area = nfp_cpp_area_alloc_acquire(cpp, cpp_id, addr, size);
1157efa766e1SChaoyong He 	if (*area == NULL) {
1158*b6de4353SZerun Fu 		PMD_DRV_LOG(ERR, "Area allocation/acquire failed for map.");
1159c7e9729dSAlejandro Lucero 		goto err_eio;
1160efa766e1SChaoyong He 	}
1161c7e9729dSAlejandro Lucero 
1162c7e9729dSAlejandro Lucero 	res = nfp_cpp_area_iomem(*area);
1163cbcbfd73SJames Hershaw 	if (res == NULL)
1164c7e9729dSAlejandro Lucero 		goto err_release_free;
1165c7e9729dSAlejandro Lucero 
1166c7e9729dSAlejandro Lucero 	return res;
1167c7e9729dSAlejandro Lucero 
1168c7e9729dSAlejandro Lucero err_release_free:
1169c7e9729dSAlejandro Lucero 	nfp_cpp_area_release_free(*area);
1170c7e9729dSAlejandro Lucero err_eio:
1171c7e9729dSAlejandro Lucero 	return NULL;
1172c7e9729dSAlejandro Lucero }
1173