xref: /dpdk/drivers/net/nfp/nfpcore/nfp_cppcore.c (revision 7be78d02)
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 
6c7e9729dSAlejandro Lucero #include <assert.h>
7c7e9729dSAlejandro Lucero #include <stdint.h>
8c7e9729dSAlejandro Lucero #include <stdio.h>
9c7e9729dSAlejandro Lucero #include <string.h>
10c7e9729dSAlejandro Lucero #include <stdlib.h>
11c7e9729dSAlejandro Lucero #include <errno.h>
12c7e9729dSAlejandro Lucero #include <sys/types.h>
13c7e9729dSAlejandro Lucero 
14c7e9729dSAlejandro Lucero #include <rte_byteorder.h>
15df96fd0dSBruce Richardson #include <ethdev_pci.h>
16c7e9729dSAlejandro Lucero 
17c7e9729dSAlejandro Lucero #include "nfp_cpp.h"
18c7e9729dSAlejandro Lucero #include "nfp_target.h"
19c7e9729dSAlejandro Lucero #include "nfp6000/nfp6000.h"
20c7e9729dSAlejandro Lucero #include "nfp6000/nfp_xpb.h"
21c7e9729dSAlejandro Lucero #include "nfp_nffw.h"
22c7e9729dSAlejandro Lucero 
23c7e9729dSAlejandro Lucero #define NFP_PL_DEVICE_ID                        0x00000004
24c7e9729dSAlejandro Lucero #define NFP_PL_DEVICE_ID_MASK                   0xff
25c0a8b024SHeinrich Kuhn #define NFP_PL_DEVICE_PART_MASK                 0xffff0000
26c0a8b024SHeinrich Kuhn #define NFP_PL_DEVICE_MODEL_MASK               (NFP_PL_DEVICE_PART_MASK | \
27c0a8b024SHeinrich Kuhn 						NFP_PL_DEVICE_ID_MASK)
28c7e9729dSAlejandro Lucero 
29c7e9729dSAlejandro Lucero void
nfp_cpp_priv_set(struct nfp_cpp * cpp,void * priv)30c7e9729dSAlejandro Lucero nfp_cpp_priv_set(struct nfp_cpp *cpp, void *priv)
31c7e9729dSAlejandro Lucero {
32c7e9729dSAlejandro Lucero 	cpp->priv = priv;
33c7e9729dSAlejandro Lucero }
34c7e9729dSAlejandro Lucero 
35c7e9729dSAlejandro Lucero void *
nfp_cpp_priv(struct nfp_cpp * cpp)36c7e9729dSAlejandro Lucero nfp_cpp_priv(struct nfp_cpp *cpp)
37c7e9729dSAlejandro Lucero {
38c7e9729dSAlejandro Lucero 	return cpp->priv;
39c7e9729dSAlejandro Lucero }
40c7e9729dSAlejandro Lucero 
41c7e9729dSAlejandro Lucero void
nfp_cpp_model_set(struct nfp_cpp * cpp,uint32_t model)42c7e9729dSAlejandro Lucero nfp_cpp_model_set(struct nfp_cpp *cpp, uint32_t model)
43c7e9729dSAlejandro Lucero {
44c7e9729dSAlejandro Lucero 	cpp->model = model;
45c7e9729dSAlejandro Lucero }
46c7e9729dSAlejandro Lucero 
47c7e9729dSAlejandro Lucero uint32_t
nfp_cpp_model(struct nfp_cpp * cpp)48c7e9729dSAlejandro Lucero nfp_cpp_model(struct nfp_cpp *cpp)
49c7e9729dSAlejandro Lucero {
50c0a8b024SHeinrich Kuhn 	int err;
51c0a8b024SHeinrich Kuhn 	uint32_t model;
52c0a8b024SHeinrich Kuhn 
53c7e9729dSAlejandro Lucero 	if (!cpp)
54c7e9729dSAlejandro Lucero 		return NFP_CPP_MODEL_INVALID;
55c7e9729dSAlejandro Lucero 
56c0a8b024SHeinrich Kuhn 	err = __nfp_cpp_model_autodetect(cpp, &model);
57c7e9729dSAlejandro Lucero 
58c0a8b024SHeinrich Kuhn 	if (err < 0)
59c0a8b024SHeinrich Kuhn 		return err;
60c0a8b024SHeinrich Kuhn 
61c0a8b024SHeinrich Kuhn 	return model;
62c7e9729dSAlejandro Lucero }
63c7e9729dSAlejandro Lucero 
64c7e9729dSAlejandro Lucero void
nfp_cpp_interface_set(struct nfp_cpp * cpp,uint32_t interface)65c7e9729dSAlejandro Lucero nfp_cpp_interface_set(struct nfp_cpp *cpp, uint32_t interface)
66c7e9729dSAlejandro Lucero {
67c7e9729dSAlejandro Lucero 	cpp->interface = interface;
68c7e9729dSAlejandro Lucero }
69c7e9729dSAlejandro Lucero 
70c7e9729dSAlejandro Lucero int
nfp_cpp_serial(struct nfp_cpp * cpp,const uint8_t ** serial)71c7e9729dSAlejandro Lucero nfp_cpp_serial(struct nfp_cpp *cpp, const uint8_t **serial)
72c7e9729dSAlejandro Lucero {
73c7e9729dSAlejandro Lucero 	*serial = cpp->serial;
74c7e9729dSAlejandro Lucero 	return cpp->serial_len;
75c7e9729dSAlejandro Lucero }
76c7e9729dSAlejandro Lucero 
77c7e9729dSAlejandro Lucero int
nfp_cpp_serial_set(struct nfp_cpp * cpp,const uint8_t * serial,size_t serial_len)78c7e9729dSAlejandro Lucero nfp_cpp_serial_set(struct nfp_cpp *cpp, const uint8_t *serial,
79c7e9729dSAlejandro Lucero 		   size_t serial_len)
80c7e9729dSAlejandro Lucero {
81c7e9729dSAlejandro Lucero 	if (cpp->serial_len)
82c7e9729dSAlejandro Lucero 		free(cpp->serial);
83c7e9729dSAlejandro Lucero 
84c7e9729dSAlejandro Lucero 	cpp->serial = malloc(serial_len);
85c7e9729dSAlejandro Lucero 	if (!cpp->serial)
86c7e9729dSAlejandro Lucero 		return -1;
87c7e9729dSAlejandro Lucero 
88c7e9729dSAlejandro Lucero 	memcpy(cpp->serial, serial, serial_len);
89c7e9729dSAlejandro Lucero 	cpp->serial_len = serial_len;
90c7e9729dSAlejandro Lucero 
91c7e9729dSAlejandro Lucero 	return 0;
92c7e9729dSAlejandro Lucero }
93c7e9729dSAlejandro Lucero 
94c7e9729dSAlejandro Lucero uint16_t
nfp_cpp_interface(struct nfp_cpp * cpp)95c7e9729dSAlejandro Lucero nfp_cpp_interface(struct nfp_cpp *cpp)
96c7e9729dSAlejandro Lucero {
97c7e9729dSAlejandro Lucero 	if (!cpp)
98c7e9729dSAlejandro Lucero 		return NFP_CPP_INTERFACE(NFP_CPP_INTERFACE_TYPE_INVALID, 0, 0);
99c7e9729dSAlejandro Lucero 
100c7e9729dSAlejandro Lucero 	return cpp->interface;
101c7e9729dSAlejandro Lucero }
102c7e9729dSAlejandro Lucero 
103c7e9729dSAlejandro Lucero void *
nfp_cpp_area_priv(struct nfp_cpp_area * cpp_area)104c7e9729dSAlejandro Lucero nfp_cpp_area_priv(struct nfp_cpp_area *cpp_area)
105c7e9729dSAlejandro Lucero {
106c7e9729dSAlejandro Lucero 	return &cpp_area[1];
107c7e9729dSAlejandro Lucero }
108c7e9729dSAlejandro Lucero 
109c7e9729dSAlejandro Lucero struct nfp_cpp *
nfp_cpp_area_cpp(struct nfp_cpp_area * cpp_area)110c7e9729dSAlejandro Lucero nfp_cpp_area_cpp(struct nfp_cpp_area *cpp_area)
111c7e9729dSAlejandro Lucero {
112c7e9729dSAlejandro Lucero 	return cpp_area->cpp;
113c7e9729dSAlejandro Lucero }
114c7e9729dSAlejandro Lucero 
115c7e9729dSAlejandro Lucero const char *
nfp_cpp_area_name(struct nfp_cpp_area * cpp_area)116c7e9729dSAlejandro Lucero nfp_cpp_area_name(struct nfp_cpp_area *cpp_area)
117c7e9729dSAlejandro Lucero {
118c7e9729dSAlejandro Lucero 	return cpp_area->name;
119c7e9729dSAlejandro Lucero }
120c7e9729dSAlejandro Lucero 
121c7e9729dSAlejandro Lucero /*
122c7e9729dSAlejandro Lucero  * nfp_cpp_area_alloc - allocate a new CPP area
123c7e9729dSAlejandro Lucero  * @cpp:    CPP handle
124c7e9729dSAlejandro Lucero  * @dest:   CPP id
125c7e9729dSAlejandro Lucero  * @address:    start address on CPP target
126c7e9729dSAlejandro Lucero  * @size:   size of area in bytes
127c7e9729dSAlejandro Lucero  *
128c7e9729dSAlejandro Lucero  * Allocate and initialize a CPP area structure.  The area must later
129c7e9729dSAlejandro Lucero  * be locked down with an 'acquire' before it can be safely accessed.
130c7e9729dSAlejandro Lucero  *
131c7e9729dSAlejandro Lucero  * NOTE: @address and @size must be 32-bit aligned values.
132c7e9729dSAlejandro Lucero  */
133c7e9729dSAlejandro Lucero struct nfp_cpp_area *
nfp_cpp_area_alloc_with_name(struct nfp_cpp * cpp,uint32_t dest,const char * name,unsigned long long address,unsigned long size)134c7e9729dSAlejandro Lucero nfp_cpp_area_alloc_with_name(struct nfp_cpp *cpp, uint32_t dest,
135c7e9729dSAlejandro Lucero 			      const char *name, unsigned long long address,
136c7e9729dSAlejandro Lucero 			      unsigned long size)
137c7e9729dSAlejandro Lucero {
138c7e9729dSAlejandro Lucero 	struct nfp_cpp_area *area;
139c7e9729dSAlejandro Lucero 	uint64_t tmp64 = (uint64_t)address;
140c7e9729dSAlejandro Lucero 	int tmp, err;
141c7e9729dSAlejandro Lucero 
142c7e9729dSAlejandro Lucero 	if (!cpp)
143c7e9729dSAlejandro Lucero 		return NULL;
144c7e9729dSAlejandro Lucero 
145c7e9729dSAlejandro Lucero 	/* CPP bus uses only a 40-bit address */
146c7e9729dSAlejandro Lucero 	if ((address + size) > (1ULL << 40))
147c7e9729dSAlejandro Lucero 		return NFP_ERRPTR(EFAULT);
148c7e9729dSAlejandro Lucero 
149c7e9729dSAlejandro Lucero 	/* Remap from cpp_island to cpp_target */
150c7e9729dSAlejandro Lucero 	err = nfp_target_cpp(dest, tmp64, &dest, &tmp64, cpp->imb_cat_table);
151c7e9729dSAlejandro Lucero 	if (err < 0)
152c7e9729dSAlejandro Lucero 		return NULL;
153c7e9729dSAlejandro Lucero 
154c7e9729dSAlejandro Lucero 	address = (unsigned long long)tmp64;
155c7e9729dSAlejandro Lucero 
156c7e9729dSAlejandro Lucero 	if (!name)
157c7e9729dSAlejandro Lucero 		name = "";
158c7e9729dSAlejandro Lucero 
159c7e9729dSAlejandro Lucero 	area = calloc(1, sizeof(*area) + cpp->op->area_priv_size +
160c7e9729dSAlejandro Lucero 		      strlen(name) + 1);
161c7e9729dSAlejandro Lucero 	if (!area)
162c7e9729dSAlejandro Lucero 		return NULL;
163c7e9729dSAlejandro Lucero 
164c7e9729dSAlejandro Lucero 	area->cpp = cpp;
165c7e9729dSAlejandro Lucero 	area->name = ((char *)area) + sizeof(*area) + cpp->op->area_priv_size;
166c7e9729dSAlejandro Lucero 	memcpy(area->name, name, strlen(name) + 1);
167c7e9729dSAlejandro Lucero 
168c7e9729dSAlejandro Lucero 	/*
169c7e9729dSAlejandro Lucero 	 * Preserve errno around the call to area_init, since most
170c7e9729dSAlejandro Lucero 	 * implementations will blindly call nfp_target_action_width()for both
171c7e9729dSAlejandro Lucero 	 * read or write modes, and that will set errno to EINVAL.
172c7e9729dSAlejandro Lucero 	 */
173c7e9729dSAlejandro Lucero 	tmp = errno;
174c7e9729dSAlejandro Lucero 
175c7e9729dSAlejandro Lucero 	err = cpp->op->area_init(area, dest, address, size);
176c7e9729dSAlejandro Lucero 	if (err < 0) {
177c7e9729dSAlejandro Lucero 		free(area);
178c7e9729dSAlejandro Lucero 		return NULL;
179c7e9729dSAlejandro Lucero 	}
180c7e9729dSAlejandro Lucero 
181c7e9729dSAlejandro Lucero 	/* Restore errno */
182c7e9729dSAlejandro Lucero 	errno = tmp;
183c7e9729dSAlejandro Lucero 
184c7e9729dSAlejandro Lucero 	area->offset = address;
185c7e9729dSAlejandro Lucero 	area->size = size;
186c7e9729dSAlejandro Lucero 
187c7e9729dSAlejandro Lucero 	return area;
188c7e9729dSAlejandro Lucero }
189c7e9729dSAlejandro Lucero 
190c7e9729dSAlejandro Lucero struct nfp_cpp_area *
nfp_cpp_area_alloc(struct nfp_cpp * cpp,uint32_t dest,unsigned long long address,unsigned long size)191c7e9729dSAlejandro Lucero nfp_cpp_area_alloc(struct nfp_cpp *cpp, uint32_t dest,
192c7e9729dSAlejandro Lucero 		    unsigned long long address, unsigned long size)
193c7e9729dSAlejandro Lucero {
194c7e9729dSAlejandro Lucero 	return nfp_cpp_area_alloc_with_name(cpp, dest, NULL, address, size);
195c7e9729dSAlejandro Lucero }
196c7e9729dSAlejandro Lucero 
197c7e9729dSAlejandro Lucero /*
198c7e9729dSAlejandro Lucero  * nfp_cpp_area_alloc_acquire - allocate a new CPP area and lock it down
199c7e9729dSAlejandro Lucero  *
200c7e9729dSAlejandro Lucero  * @cpp:    CPP handle
201c7e9729dSAlejandro Lucero  * @dest:   CPP id
202c7e9729dSAlejandro Lucero  * @address:    start address on CPP target
203c7e9729dSAlejandro Lucero  * @size:   size of area
204c7e9729dSAlejandro Lucero  *
205*7be78d02SJosh Soref  * Allocate and initialize a CPP area structure, and lock it down so
206c7e9729dSAlejandro Lucero  * that it can be accessed directly.
207c7e9729dSAlejandro Lucero  *
208c7e9729dSAlejandro Lucero  * NOTE: @address and @size must be 32-bit aligned values.
209c7e9729dSAlejandro Lucero  *
210c7e9729dSAlejandro Lucero  * NOTE: The area must also be 'released' when the structure is freed.
211c7e9729dSAlejandro Lucero  */
212c7e9729dSAlejandro Lucero struct nfp_cpp_area *
nfp_cpp_area_alloc_acquire(struct nfp_cpp * cpp,uint32_t destination,unsigned long long address,unsigned long size)213c7e9729dSAlejandro Lucero nfp_cpp_area_alloc_acquire(struct nfp_cpp *cpp, uint32_t destination,
214c7e9729dSAlejandro Lucero 			    unsigned long long address, unsigned long size)
215c7e9729dSAlejandro Lucero {
216c7e9729dSAlejandro Lucero 	struct nfp_cpp_area *area;
217c7e9729dSAlejandro Lucero 
218c7e9729dSAlejandro Lucero 	area = nfp_cpp_area_alloc(cpp, destination, address, size);
219c7e9729dSAlejandro Lucero 	if (!area)
220c7e9729dSAlejandro Lucero 		return NULL;
221c7e9729dSAlejandro Lucero 
222c7e9729dSAlejandro Lucero 	if (nfp_cpp_area_acquire(area)) {
223c7e9729dSAlejandro Lucero 		nfp_cpp_area_free(area);
224c7e9729dSAlejandro Lucero 		return NULL;
225c7e9729dSAlejandro Lucero 	}
226c7e9729dSAlejandro Lucero 
227c7e9729dSAlejandro Lucero 	return area;
228c7e9729dSAlejandro Lucero }
229c7e9729dSAlejandro Lucero 
230c7e9729dSAlejandro Lucero /*
231c7e9729dSAlejandro Lucero  * nfp_cpp_area_free - free up the CPP area
232c7e9729dSAlejandro Lucero  * area:    CPP area handle
233c7e9729dSAlejandro Lucero  *
234c7e9729dSAlejandro Lucero  * Frees up memory resources held by the CPP area.
235c7e9729dSAlejandro Lucero  */
236c7e9729dSAlejandro Lucero void
nfp_cpp_area_free(struct nfp_cpp_area * area)237c7e9729dSAlejandro Lucero nfp_cpp_area_free(struct nfp_cpp_area *area)
238c7e9729dSAlejandro Lucero {
239c7e9729dSAlejandro Lucero 	if (area->cpp->op->area_cleanup)
240c7e9729dSAlejandro Lucero 		area->cpp->op->area_cleanup(area);
241c7e9729dSAlejandro Lucero 	free(area);
242c7e9729dSAlejandro Lucero }
243c7e9729dSAlejandro Lucero 
244c7e9729dSAlejandro Lucero /*
245c7e9729dSAlejandro Lucero  * nfp_cpp_area_release_free - release CPP area and free it
246c7e9729dSAlejandro Lucero  * area:    CPP area handle
247c7e9729dSAlejandro Lucero  *
248c7e9729dSAlejandro Lucero  * Releases CPP area and frees up memory resources held by the it.
249c7e9729dSAlejandro Lucero  */
250c7e9729dSAlejandro Lucero void
nfp_cpp_area_release_free(struct nfp_cpp_area * area)251c7e9729dSAlejandro Lucero nfp_cpp_area_release_free(struct nfp_cpp_area *area)
252c7e9729dSAlejandro Lucero {
253c7e9729dSAlejandro Lucero 	nfp_cpp_area_release(area);
254c7e9729dSAlejandro Lucero 	nfp_cpp_area_free(area);
255c7e9729dSAlejandro Lucero }
256c7e9729dSAlejandro Lucero 
257c7e9729dSAlejandro Lucero /*
258c7e9729dSAlejandro Lucero  * nfp_cpp_area_acquire - lock down a CPP area for access
259c7e9729dSAlejandro Lucero  * @area:   CPP area handle
260c7e9729dSAlejandro Lucero  *
261c7e9729dSAlejandro Lucero  * Locks down the CPP area for a potential long term activity.  Area
262c7e9729dSAlejandro Lucero  * must always be locked down before being accessed.
263c7e9729dSAlejandro Lucero  */
264c7e9729dSAlejandro Lucero int
nfp_cpp_area_acquire(struct nfp_cpp_area * area)265c7e9729dSAlejandro Lucero nfp_cpp_area_acquire(struct nfp_cpp_area *area)
266c7e9729dSAlejandro Lucero {
267c7e9729dSAlejandro Lucero 	if (area->cpp->op->area_acquire) {
268c7e9729dSAlejandro Lucero 		int err = area->cpp->op->area_acquire(area);
269c7e9729dSAlejandro Lucero 
270c7e9729dSAlejandro Lucero 		if (err < 0)
271c7e9729dSAlejandro Lucero 			return -1;
272c7e9729dSAlejandro Lucero 	}
273c7e9729dSAlejandro Lucero 
274c7e9729dSAlejandro Lucero 	return 0;
275c7e9729dSAlejandro Lucero }
276c7e9729dSAlejandro Lucero 
277c7e9729dSAlejandro Lucero /*
278c7e9729dSAlejandro Lucero  * nfp_cpp_area_release - release a locked down CPP area
279c7e9729dSAlejandro Lucero  * @area:   CPP area handle
280c7e9729dSAlejandro Lucero  *
281c7e9729dSAlejandro Lucero  * Releases a previously locked down CPP area.
282c7e9729dSAlejandro Lucero  */
283c7e9729dSAlejandro Lucero void
nfp_cpp_area_release(struct nfp_cpp_area * area)284c7e9729dSAlejandro Lucero nfp_cpp_area_release(struct nfp_cpp_area *area)
285c7e9729dSAlejandro Lucero {
286c7e9729dSAlejandro Lucero 	if (area->cpp->op->area_release)
287c7e9729dSAlejandro Lucero 		area->cpp->op->area_release(area);
288c7e9729dSAlejandro Lucero }
289c7e9729dSAlejandro Lucero 
290c7e9729dSAlejandro Lucero /*
291c7e9729dSAlejandro Lucero  * nfp_cpp_area_iomem() - get IOMEM region for CPP area
292c7e9729dSAlejandro Lucero  *
293c7e9729dSAlejandro Lucero  * @area:       CPP area handle
294c7e9729dSAlejandro Lucero  *
295c7e9729dSAlejandro Lucero  * Returns an iomem pointer for use with readl()/writel() style operations.
296c7e9729dSAlejandro Lucero  *
297c7e9729dSAlejandro Lucero  * NOTE: Area must have been locked down with an 'acquire'.
298c7e9729dSAlejandro Lucero  *
299c7e9729dSAlejandro Lucero  * Return: pointer to the area, or NULL
300c7e9729dSAlejandro Lucero  */
301c7e9729dSAlejandro Lucero void *
nfp_cpp_area_iomem(struct nfp_cpp_area * area)302c7e9729dSAlejandro Lucero nfp_cpp_area_iomem(struct nfp_cpp_area *area)
303c7e9729dSAlejandro Lucero {
304c7e9729dSAlejandro Lucero 	void *iomem = NULL;
305c7e9729dSAlejandro Lucero 
306c7e9729dSAlejandro Lucero 	if (area->cpp->op->area_iomem)
307c7e9729dSAlejandro Lucero 		iomem = area->cpp->op->area_iomem(area);
308c7e9729dSAlejandro Lucero 
309c7e9729dSAlejandro Lucero 	return iomem;
310c7e9729dSAlejandro Lucero }
311c7e9729dSAlejandro Lucero 
312c7e9729dSAlejandro Lucero /*
313c7e9729dSAlejandro Lucero  * nfp_cpp_area_read - read data from CPP area
314c7e9729dSAlejandro Lucero  *
315c7e9729dSAlejandro Lucero  * @area:       CPP area handle
316c7e9729dSAlejandro Lucero  * @offset:     offset into CPP area
317c7e9729dSAlejandro Lucero  * @kernel_vaddr:   kernel address to put data into
318c7e9729dSAlejandro Lucero  * @length:     number of bytes to read
319c7e9729dSAlejandro Lucero  *
320c7e9729dSAlejandro Lucero  * Read data from indicated CPP region.
321c7e9729dSAlejandro Lucero  *
322c7e9729dSAlejandro Lucero  * NOTE: @offset and @length must be 32-bit aligned values.
323c7e9729dSAlejandro Lucero  *
324c7e9729dSAlejandro Lucero  * NOTE: Area must have been locked down with an 'acquire'.
325c7e9729dSAlejandro Lucero  */
326c7e9729dSAlejandro Lucero int
nfp_cpp_area_read(struct nfp_cpp_area * area,unsigned long offset,void * kernel_vaddr,size_t length)327c7e9729dSAlejandro Lucero nfp_cpp_area_read(struct nfp_cpp_area *area, unsigned long offset,
328c7e9729dSAlejandro Lucero 		  void *kernel_vaddr, size_t length)
329c7e9729dSAlejandro Lucero {
330c7e9729dSAlejandro Lucero 	if ((offset + length) > area->size)
331c7e9729dSAlejandro Lucero 		return NFP_ERRNO(EFAULT);
332c7e9729dSAlejandro Lucero 
333c7e9729dSAlejandro Lucero 	return area->cpp->op->area_read(area, kernel_vaddr, offset, length);
334c7e9729dSAlejandro Lucero }
335c7e9729dSAlejandro Lucero 
336c7e9729dSAlejandro Lucero /*
337c7e9729dSAlejandro Lucero  * nfp_cpp_area_write - write data to CPP area
338c7e9729dSAlejandro Lucero  *
339c7e9729dSAlejandro Lucero  * @area:       CPP area handle
340c7e9729dSAlejandro Lucero  * @offset:     offset into CPP area
341c7e9729dSAlejandro Lucero  * @kernel_vaddr:   kernel address to read data from
342c7e9729dSAlejandro Lucero  * @length:     number of bytes to write
343c7e9729dSAlejandro Lucero  *
344c7e9729dSAlejandro Lucero  * Write data to indicated CPP region.
345c7e9729dSAlejandro Lucero  *
346c7e9729dSAlejandro Lucero  * NOTE: @offset and @length must be 32-bit aligned values.
347c7e9729dSAlejandro Lucero  *
348c7e9729dSAlejandro Lucero  * NOTE: Area must have been locked down with an 'acquire'.
349c7e9729dSAlejandro Lucero  */
350c7e9729dSAlejandro Lucero int
nfp_cpp_area_write(struct nfp_cpp_area * area,unsigned long offset,const void * kernel_vaddr,size_t length)351c7e9729dSAlejandro Lucero nfp_cpp_area_write(struct nfp_cpp_area *area, unsigned long offset,
352c7e9729dSAlejandro Lucero 		   const void *kernel_vaddr, size_t length)
353c7e9729dSAlejandro Lucero {
354c7e9729dSAlejandro Lucero 	if ((offset + length) > area->size)
355c7e9729dSAlejandro Lucero 		return NFP_ERRNO(EFAULT);
356c7e9729dSAlejandro Lucero 
357c7e9729dSAlejandro Lucero 	return area->cpp->op->area_write(area, kernel_vaddr, offset, length);
358c7e9729dSAlejandro Lucero }
359c7e9729dSAlejandro Lucero 
360c7e9729dSAlejandro Lucero void *
nfp_cpp_area_mapped(struct nfp_cpp_area * area)361c7e9729dSAlejandro Lucero nfp_cpp_area_mapped(struct nfp_cpp_area *area)
362c7e9729dSAlejandro Lucero {
363c7e9729dSAlejandro Lucero 	if (area->cpp->op->area_mapped)
364c7e9729dSAlejandro Lucero 		return area->cpp->op->area_mapped(area);
365c7e9729dSAlejandro Lucero 	return NULL;
366c7e9729dSAlejandro Lucero }
367c7e9729dSAlejandro Lucero 
368c7e9729dSAlejandro Lucero /*
369c7e9729dSAlejandro Lucero  * nfp_cpp_area_check_range - check if address range fits in CPP area
370c7e9729dSAlejandro Lucero  *
371c7e9729dSAlejandro Lucero  * @area:   CPP area handle
372c7e9729dSAlejandro Lucero  * @offset: offset into CPP area
373c7e9729dSAlejandro Lucero  * @length: size of address range in bytes
374c7e9729dSAlejandro Lucero  *
375c7e9729dSAlejandro Lucero  * Check if address range fits within CPP area.  Return 0 if area fits
376c7e9729dSAlejandro Lucero  * or -1 on error.
377c7e9729dSAlejandro Lucero  */
378c7e9729dSAlejandro Lucero int
nfp_cpp_area_check_range(struct nfp_cpp_area * area,unsigned long long offset,unsigned long length)379c7e9729dSAlejandro Lucero nfp_cpp_area_check_range(struct nfp_cpp_area *area, unsigned long long offset,
380c7e9729dSAlejandro Lucero 			 unsigned long length)
381c7e9729dSAlejandro Lucero {
382c7e9729dSAlejandro Lucero 	if (((offset + length) > area->size))
383c7e9729dSAlejandro Lucero 		return NFP_ERRNO(EFAULT);
384c7e9729dSAlejandro Lucero 
385c7e9729dSAlejandro Lucero 	return 0;
386c7e9729dSAlejandro Lucero }
387c7e9729dSAlejandro Lucero 
388c7e9729dSAlejandro Lucero /*
389c7e9729dSAlejandro Lucero  * Return the correct CPP address, and fixup xpb_addr as needed,
390c7e9729dSAlejandro Lucero  * based upon NFP model.
391c7e9729dSAlejandro Lucero  */
392c7e9729dSAlejandro Lucero static uint32_t
nfp_xpb_to_cpp(struct nfp_cpp * cpp,uint32_t * xpb_addr)393c7e9729dSAlejandro Lucero nfp_xpb_to_cpp(struct nfp_cpp *cpp, uint32_t *xpb_addr)
394c7e9729dSAlejandro Lucero {
395c7e9729dSAlejandro Lucero 	uint32_t xpb;
396c7e9729dSAlejandro Lucero 	int island;
397c7e9729dSAlejandro Lucero 
398c7e9729dSAlejandro Lucero 	xpb = NFP_CPP_ID(14, NFP_CPP_ACTION_RW, 0);
399c7e9729dSAlejandro Lucero 
400c7e9729dSAlejandro Lucero 	/*
401c7e9729dSAlejandro Lucero 	 * Ensure that non-local XPB accesses go out through the
402c7e9729dSAlejandro Lucero 	 * global XPBM bus.
403c7e9729dSAlejandro Lucero 	 */
404c7e9729dSAlejandro Lucero 	island = ((*xpb_addr) >> 24) & 0x3f;
405c7e9729dSAlejandro Lucero 
406c7e9729dSAlejandro Lucero 	if (!island)
407c7e9729dSAlejandro Lucero 		return xpb;
408c7e9729dSAlejandro Lucero 
409c7e9729dSAlejandro Lucero 	if (island == 1) {
410c7e9729dSAlejandro Lucero 		/*
411c7e9729dSAlejandro Lucero 		 * Accesses to the ARM Island overlay uses Island 0
412c7e9729dSAlejandro Lucero 		 * Global Bit
413c7e9729dSAlejandro Lucero 		 */
414c7e9729dSAlejandro Lucero 		(*xpb_addr) &= ~0x7f000000;
415c7e9729dSAlejandro Lucero 		if (*xpb_addr < 0x60000)
416c7e9729dSAlejandro Lucero 			*xpb_addr |= (1 << 30);
417c7e9729dSAlejandro Lucero 		else
418c7e9729dSAlejandro Lucero 			/* And only non-ARM interfaces use island id = 1 */
419c7e9729dSAlejandro Lucero 			if (NFP_CPP_INTERFACE_TYPE_of(nfp_cpp_interface(cpp)) !=
420c7e9729dSAlejandro Lucero 			    NFP_CPP_INTERFACE_TYPE_ARM)
421c7e9729dSAlejandro Lucero 				*xpb_addr |= (1 << 24);
422c7e9729dSAlejandro Lucero 	} else {
423c7e9729dSAlejandro Lucero 		(*xpb_addr) |= (1 << 30);
424c7e9729dSAlejandro Lucero 	}
425c7e9729dSAlejandro Lucero 
426c7e9729dSAlejandro Lucero 	return xpb;
427c7e9729dSAlejandro Lucero }
428c7e9729dSAlejandro Lucero 
429c7e9729dSAlejandro Lucero int
nfp_cpp_area_readl(struct nfp_cpp_area * area,unsigned long offset,uint32_t * value)430c7e9729dSAlejandro Lucero nfp_cpp_area_readl(struct nfp_cpp_area *area, unsigned long offset,
431c7e9729dSAlejandro Lucero 		   uint32_t *value)
432c7e9729dSAlejandro Lucero {
433c7e9729dSAlejandro Lucero 	int sz;
434c7e9729dSAlejandro Lucero 	uint32_t tmp = 0;
435c7e9729dSAlejandro Lucero 
436c7e9729dSAlejandro Lucero 	sz = nfp_cpp_area_read(area, offset, &tmp, sizeof(tmp));
437c7e9729dSAlejandro Lucero 	*value = rte_le_to_cpu_32(tmp);
438c7e9729dSAlejandro Lucero 
439c7e9729dSAlejandro Lucero 	return (sz == sizeof(*value)) ? 0 : -1;
440c7e9729dSAlejandro Lucero }
441c7e9729dSAlejandro Lucero 
442c7e9729dSAlejandro Lucero int
nfp_cpp_area_writel(struct nfp_cpp_area * area,unsigned long offset,uint32_t value)443c7e9729dSAlejandro Lucero nfp_cpp_area_writel(struct nfp_cpp_area *area, unsigned long offset,
444c7e9729dSAlejandro Lucero 		    uint32_t value)
445c7e9729dSAlejandro Lucero {
446c7e9729dSAlejandro Lucero 	int sz;
447c7e9729dSAlejandro Lucero 
448c7e9729dSAlejandro Lucero 	value = rte_cpu_to_le_32(value);
449c7e9729dSAlejandro Lucero 	sz = nfp_cpp_area_write(area, offset, &value, sizeof(value));
450c7e9729dSAlejandro Lucero 	return (sz == sizeof(value)) ? 0 : -1;
451c7e9729dSAlejandro Lucero }
452c7e9729dSAlejandro Lucero 
453c7e9729dSAlejandro Lucero int
nfp_cpp_area_readq(struct nfp_cpp_area * area,unsigned long offset,uint64_t * value)454c7e9729dSAlejandro Lucero nfp_cpp_area_readq(struct nfp_cpp_area *area, unsigned long offset,
455c7e9729dSAlejandro Lucero 		   uint64_t *value)
456c7e9729dSAlejandro Lucero {
457c7e9729dSAlejandro Lucero 	int sz;
458c7e9729dSAlejandro Lucero 	uint64_t tmp = 0;
459c7e9729dSAlejandro Lucero 
460c7e9729dSAlejandro Lucero 	sz = nfp_cpp_area_read(area, offset, &tmp, sizeof(tmp));
461c7e9729dSAlejandro Lucero 	*value = rte_le_to_cpu_64(tmp);
462c7e9729dSAlejandro Lucero 
463c7e9729dSAlejandro Lucero 	return (sz == sizeof(*value)) ? 0 : -1;
464c7e9729dSAlejandro Lucero }
465c7e9729dSAlejandro Lucero 
466c7e9729dSAlejandro Lucero int
nfp_cpp_area_writeq(struct nfp_cpp_area * area,unsigned long offset,uint64_t value)467c7e9729dSAlejandro Lucero nfp_cpp_area_writeq(struct nfp_cpp_area *area, unsigned long offset,
468c7e9729dSAlejandro Lucero 		    uint64_t value)
469c7e9729dSAlejandro Lucero {
470c7e9729dSAlejandro Lucero 	int sz;
471c7e9729dSAlejandro Lucero 
472c7e9729dSAlejandro Lucero 	value = rte_cpu_to_le_64(value);
473c7e9729dSAlejandro Lucero 	sz = nfp_cpp_area_write(area, offset, &value, sizeof(value));
474c7e9729dSAlejandro Lucero 
475c7e9729dSAlejandro Lucero 	return (sz == sizeof(value)) ? 0 : -1;
476c7e9729dSAlejandro Lucero }
477c7e9729dSAlejandro Lucero 
478c7e9729dSAlejandro Lucero int
nfp_cpp_readl(struct nfp_cpp * cpp,uint32_t cpp_id,unsigned long long address,uint32_t * value)479c7e9729dSAlejandro Lucero nfp_cpp_readl(struct nfp_cpp *cpp, uint32_t cpp_id, unsigned long long address,
480c7e9729dSAlejandro Lucero 	      uint32_t *value)
481c7e9729dSAlejandro Lucero {
482c7e9729dSAlejandro Lucero 	int sz;
483c7e9729dSAlejandro Lucero 	uint32_t tmp;
484c7e9729dSAlejandro Lucero 
485c7e9729dSAlejandro Lucero 	sz = nfp_cpp_read(cpp, cpp_id, address, &tmp, sizeof(tmp));
486c7e9729dSAlejandro Lucero 	*value = rte_le_to_cpu_32(tmp);
487c7e9729dSAlejandro Lucero 
488c7e9729dSAlejandro Lucero 	return (sz == sizeof(*value)) ? 0 : -1;
489c7e9729dSAlejandro Lucero }
490c7e9729dSAlejandro Lucero 
491c7e9729dSAlejandro Lucero int
nfp_cpp_writel(struct nfp_cpp * cpp,uint32_t cpp_id,unsigned long long address,uint32_t value)492c7e9729dSAlejandro Lucero nfp_cpp_writel(struct nfp_cpp *cpp, uint32_t cpp_id, unsigned long long address,
493c7e9729dSAlejandro Lucero 	       uint32_t value)
494c7e9729dSAlejandro Lucero {
495c7e9729dSAlejandro Lucero 	int sz;
496c7e9729dSAlejandro Lucero 
497c7e9729dSAlejandro Lucero 	value = rte_cpu_to_le_32(value);
498c7e9729dSAlejandro Lucero 	sz = nfp_cpp_write(cpp, cpp_id, address, &value, sizeof(value));
499c7e9729dSAlejandro Lucero 
500c7e9729dSAlejandro Lucero 	return (sz == sizeof(value)) ? 0 : -1;
501c7e9729dSAlejandro Lucero }
502c7e9729dSAlejandro Lucero 
503c7e9729dSAlejandro Lucero int
nfp_cpp_readq(struct nfp_cpp * cpp,uint32_t cpp_id,unsigned long long address,uint64_t * value)504c7e9729dSAlejandro Lucero nfp_cpp_readq(struct nfp_cpp *cpp, uint32_t cpp_id, unsigned long long address,
505c7e9729dSAlejandro Lucero 	      uint64_t *value)
506c7e9729dSAlejandro Lucero {
507c7e9729dSAlejandro Lucero 	int sz;
508c7e9729dSAlejandro Lucero 	uint64_t tmp;
509c7e9729dSAlejandro Lucero 
510c7e9729dSAlejandro Lucero 	sz = nfp_cpp_read(cpp, cpp_id, address, &tmp, sizeof(tmp));
511c7e9729dSAlejandro Lucero 	*value = rte_le_to_cpu_64(tmp);
512c7e9729dSAlejandro Lucero 
513c7e9729dSAlejandro Lucero 	return (sz == sizeof(*value)) ? 0 : -1;
514c7e9729dSAlejandro Lucero }
515c7e9729dSAlejandro Lucero 
516c7e9729dSAlejandro Lucero int
nfp_cpp_writeq(struct nfp_cpp * cpp,uint32_t cpp_id,unsigned long long address,uint64_t value)517c7e9729dSAlejandro Lucero nfp_cpp_writeq(struct nfp_cpp *cpp, uint32_t cpp_id, unsigned long long address,
518c7e9729dSAlejandro Lucero 	       uint64_t value)
519c7e9729dSAlejandro Lucero {
520c7e9729dSAlejandro Lucero 	int sz;
521c7e9729dSAlejandro Lucero 
522c7e9729dSAlejandro Lucero 	value = rte_cpu_to_le_64(value);
523c7e9729dSAlejandro Lucero 	sz = nfp_cpp_write(cpp, cpp_id, address, &value, sizeof(value));
524c7e9729dSAlejandro Lucero 
525c7e9729dSAlejandro Lucero 	return (sz == sizeof(value)) ? 0 : -1;
526c7e9729dSAlejandro Lucero }
527c7e9729dSAlejandro Lucero 
528c7e9729dSAlejandro Lucero int
nfp_xpb_writel(struct nfp_cpp * cpp,uint32_t xpb_addr,uint32_t value)529c7e9729dSAlejandro Lucero nfp_xpb_writel(struct nfp_cpp *cpp, uint32_t xpb_addr, uint32_t value)
530c7e9729dSAlejandro Lucero {
531c7e9729dSAlejandro Lucero 	uint32_t cpp_dest;
532c7e9729dSAlejandro Lucero 
533c7e9729dSAlejandro Lucero 	cpp_dest = nfp_xpb_to_cpp(cpp, &xpb_addr);
534c7e9729dSAlejandro Lucero 
535c7e9729dSAlejandro Lucero 	return nfp_cpp_writel(cpp, cpp_dest, xpb_addr, value);
536c7e9729dSAlejandro Lucero }
537c7e9729dSAlejandro Lucero 
538c7e9729dSAlejandro Lucero int
nfp_xpb_readl(struct nfp_cpp * cpp,uint32_t xpb_addr,uint32_t * value)539c7e9729dSAlejandro Lucero nfp_xpb_readl(struct nfp_cpp *cpp, uint32_t xpb_addr, uint32_t *value)
540c7e9729dSAlejandro Lucero {
541c7e9729dSAlejandro Lucero 	uint32_t cpp_dest;
542c7e9729dSAlejandro Lucero 
543c7e9729dSAlejandro Lucero 	cpp_dest = nfp_xpb_to_cpp(cpp, &xpb_addr);
544c7e9729dSAlejandro Lucero 
545c7e9729dSAlejandro Lucero 	return nfp_cpp_readl(cpp, cpp_dest, xpb_addr, value);
546c7e9729dSAlejandro Lucero }
547c7e9729dSAlejandro Lucero 
548c7e9729dSAlejandro Lucero static struct nfp_cpp *
nfp_cpp_alloc(struct rte_pci_device * dev,int driver_lock_needed)549ebf2ed72SAlejandro Lucero nfp_cpp_alloc(struct rte_pci_device *dev, int driver_lock_needed)
550c7e9729dSAlejandro Lucero {
551c7e9729dSAlejandro Lucero 	const struct nfp_cpp_operations *ops;
552c7e9729dSAlejandro Lucero 	struct nfp_cpp *cpp;
553c7e9729dSAlejandro Lucero 	int err;
554c7e9729dSAlejandro Lucero 
555c7e9729dSAlejandro Lucero 	ops = nfp_cpp_transport_operations();
556c7e9729dSAlejandro Lucero 
557c7e9729dSAlejandro Lucero 	if (!ops || !ops->init)
558c7e9729dSAlejandro Lucero 		return NFP_ERRPTR(EINVAL);
559c7e9729dSAlejandro Lucero 
560c7e9729dSAlejandro Lucero 	cpp = calloc(1, sizeof(*cpp));
561c7e9729dSAlejandro Lucero 	if (!cpp)
562c7e9729dSAlejandro Lucero 		return NULL;
563c7e9729dSAlejandro Lucero 
564c7e9729dSAlejandro Lucero 	cpp->op = ops;
5655f6ed2f4SAlejandro Lucero 	cpp->driver_lock_needed = driver_lock_needed;
566c7e9729dSAlejandro Lucero 
567c7e9729dSAlejandro Lucero 	if (cpp->op->init) {
568ebf2ed72SAlejandro Lucero 		err = cpp->op->init(cpp, dev);
569c7e9729dSAlejandro Lucero 		if (err < 0) {
570c7e9729dSAlejandro Lucero 			free(cpp);
571c7e9729dSAlejandro Lucero 			return NULL;
572c7e9729dSAlejandro Lucero 		}
573c7e9729dSAlejandro Lucero 	}
574c7e9729dSAlejandro Lucero 
575c7e9729dSAlejandro Lucero 	if (NFP_CPP_MODEL_IS_6000(nfp_cpp_model(cpp))) {
576c7e9729dSAlejandro Lucero 		uint32_t xpbaddr;
577c7e9729dSAlejandro Lucero 		size_t tgt;
578c7e9729dSAlejandro Lucero 
579c7e9729dSAlejandro Lucero 		for (tgt = 0; tgt < ARRAY_SIZE(cpp->imb_cat_table); tgt++) {
580c7e9729dSAlejandro Lucero 			/* Hardcoded XPB IMB Base, island 0 */
581c7e9729dSAlejandro Lucero 			xpbaddr = 0x000a0000 + (tgt * 4);
582c7e9729dSAlejandro Lucero 			err = nfp_xpb_readl(cpp, xpbaddr,
583c7e9729dSAlejandro Lucero 				(uint32_t *)&cpp->imb_cat_table[tgt]);
584c7e9729dSAlejandro Lucero 			if (err < 0) {
585c7e9729dSAlejandro Lucero 				free(cpp);
586c7e9729dSAlejandro Lucero 				return NULL;
587c7e9729dSAlejandro Lucero 			}
588c7e9729dSAlejandro Lucero 		}
589c7e9729dSAlejandro Lucero 	}
590c7e9729dSAlejandro Lucero 
591c7e9729dSAlejandro Lucero 	return cpp;
592c7e9729dSAlejandro Lucero }
593c7e9729dSAlejandro Lucero 
594c7e9729dSAlejandro Lucero /*
595c7e9729dSAlejandro Lucero  * nfp_cpp_free - free the CPP handle
596c7e9729dSAlejandro Lucero  * @cpp:    CPP handle
597c7e9729dSAlejandro Lucero  */
598c7e9729dSAlejandro Lucero void
nfp_cpp_free(struct nfp_cpp * cpp)599c7e9729dSAlejandro Lucero nfp_cpp_free(struct nfp_cpp *cpp)
600c7e9729dSAlejandro Lucero {
601c7e9729dSAlejandro Lucero 	if (cpp->op && cpp->op->free)
602c7e9729dSAlejandro Lucero 		cpp->op->free(cpp);
603c7e9729dSAlejandro Lucero 
604c7e9729dSAlejandro Lucero 	if (cpp->serial_len)
605c7e9729dSAlejandro Lucero 		free(cpp->serial);
606c7e9729dSAlejandro Lucero 
607c7e9729dSAlejandro Lucero 	free(cpp);
608c7e9729dSAlejandro Lucero }
609c7e9729dSAlejandro Lucero 
610c7e9729dSAlejandro Lucero struct nfp_cpp *
nfp_cpp_from_device_name(struct rte_pci_device * dev,int driver_lock_needed)611ebf2ed72SAlejandro Lucero nfp_cpp_from_device_name(struct rte_pci_device *dev, int driver_lock_needed)
612c7e9729dSAlejandro Lucero {
613ebf2ed72SAlejandro Lucero 	return nfp_cpp_alloc(dev, driver_lock_needed);
614c7e9729dSAlejandro Lucero }
615c7e9729dSAlejandro Lucero 
616c7e9729dSAlejandro Lucero /*
617c7e9729dSAlejandro Lucero  * Modify bits of a 32-bit value from the XPB bus
618c7e9729dSAlejandro Lucero  *
619c7e9729dSAlejandro Lucero  * @param cpp           NFP CPP device handle
620c7e9729dSAlejandro Lucero  * @param xpb_tgt       XPB target and address
621c7e9729dSAlejandro Lucero  * @param mask          mask of bits to alter
622c7e9729dSAlejandro Lucero  * @param value         value to modify
623c7e9729dSAlejandro Lucero  *
624c7e9729dSAlejandro Lucero  * @return 0 on success, or -1 on failure (and set errno accordingly).
625c7e9729dSAlejandro Lucero  */
626c7e9729dSAlejandro Lucero int
nfp_xpb_writelm(struct nfp_cpp * cpp,uint32_t xpb_tgt,uint32_t mask,uint32_t value)627c7e9729dSAlejandro Lucero nfp_xpb_writelm(struct nfp_cpp *cpp, uint32_t xpb_tgt, uint32_t mask,
628c7e9729dSAlejandro Lucero 		uint32_t value)
629c7e9729dSAlejandro Lucero {
630c7e9729dSAlejandro Lucero 	int err;
631c7e9729dSAlejandro Lucero 	uint32_t tmp;
632c7e9729dSAlejandro Lucero 
633c7e9729dSAlejandro Lucero 	err = nfp_xpb_readl(cpp, xpb_tgt, &tmp);
634c7e9729dSAlejandro Lucero 	if (err < 0)
635c7e9729dSAlejandro Lucero 		return err;
636c7e9729dSAlejandro Lucero 
637c7e9729dSAlejandro Lucero 	tmp &= ~mask;
638c7e9729dSAlejandro Lucero 	tmp |= (mask & value);
639c7e9729dSAlejandro Lucero 	return nfp_xpb_writel(cpp, xpb_tgt, tmp);
640c7e9729dSAlejandro Lucero }
641c7e9729dSAlejandro Lucero 
642c7e9729dSAlejandro Lucero /*
643c7e9729dSAlejandro Lucero  * Modify bits of a 32-bit value from the XPB bus
644c7e9729dSAlejandro Lucero  *
645c7e9729dSAlejandro Lucero  * @param cpp           NFP CPP device handle
646c7e9729dSAlejandro Lucero  * @param xpb_tgt       XPB target and address
647c7e9729dSAlejandro Lucero  * @param mask          mask of bits to alter
648c7e9729dSAlejandro Lucero  * @param value         value to monitor for
649c7e9729dSAlejandro Lucero  * @param timeout_us    maximum number of us to wait (-1 for forever)
650c7e9729dSAlejandro Lucero  *
651c7e9729dSAlejandro Lucero  * @return >= 0 on success, or -1 on failure (and set errno accordingly).
652c7e9729dSAlejandro Lucero  */
653c7e9729dSAlejandro Lucero int
nfp_xpb_waitlm(struct nfp_cpp * cpp,uint32_t xpb_tgt,uint32_t mask,uint32_t value,int timeout_us)654c7e9729dSAlejandro Lucero nfp_xpb_waitlm(struct nfp_cpp *cpp, uint32_t xpb_tgt, uint32_t mask,
655c7e9729dSAlejandro Lucero 	       uint32_t value, int timeout_us)
656c7e9729dSAlejandro Lucero {
657c7e9729dSAlejandro Lucero 	uint32_t tmp;
658c7e9729dSAlejandro Lucero 	int err;
659c7e9729dSAlejandro Lucero 
660c7e9729dSAlejandro Lucero 	do {
661c7e9729dSAlejandro Lucero 		err = nfp_xpb_readl(cpp, xpb_tgt, &tmp);
662c7e9729dSAlejandro Lucero 		if (err < 0)
663c7e9729dSAlejandro Lucero 			goto exit;
664c7e9729dSAlejandro Lucero 
665c7e9729dSAlejandro Lucero 		if ((tmp & mask) == (value & mask)) {
666c7e9729dSAlejandro Lucero 			if (timeout_us < 0)
667c7e9729dSAlejandro Lucero 				timeout_us = 0;
668c7e9729dSAlejandro Lucero 			break;
669c7e9729dSAlejandro Lucero 		}
670c7e9729dSAlejandro Lucero 
671c7e9729dSAlejandro Lucero 		if (timeout_us < 0)
672c7e9729dSAlejandro Lucero 			continue;
673c7e9729dSAlejandro Lucero 
674c7e9729dSAlejandro Lucero 		timeout_us -= 100;
675c7e9729dSAlejandro Lucero 		usleep(100);
676c7e9729dSAlejandro Lucero 	} while (timeout_us >= 0);
677c7e9729dSAlejandro Lucero 
678c7e9729dSAlejandro Lucero 	if (timeout_us < 0)
679c7e9729dSAlejandro Lucero 		err = NFP_ERRNO(ETIMEDOUT);
680c7e9729dSAlejandro Lucero 	else
681c7e9729dSAlejandro Lucero 		err = timeout_us;
682c7e9729dSAlejandro Lucero 
683c7e9729dSAlejandro Lucero exit:
684c7e9729dSAlejandro Lucero 	return err;
685c7e9729dSAlejandro Lucero }
686c7e9729dSAlejandro Lucero 
687c7e9729dSAlejandro Lucero /*
688c7e9729dSAlejandro Lucero  * nfp_cpp_read - read from CPP target
689c7e9729dSAlejandro Lucero  * @cpp:        CPP handle
690c7e9729dSAlejandro Lucero  * @destination:    CPP id
691c7e9729dSAlejandro Lucero  * @address:        offset into CPP target
692c7e9729dSAlejandro Lucero  * @kernel_vaddr:   kernel buffer for result
693c7e9729dSAlejandro Lucero  * @length:     number of bytes to read
694c7e9729dSAlejandro Lucero  */
695c7e9729dSAlejandro Lucero int
nfp_cpp_read(struct nfp_cpp * cpp,uint32_t destination,unsigned long long address,void * kernel_vaddr,size_t length)696c7e9729dSAlejandro Lucero nfp_cpp_read(struct nfp_cpp *cpp, uint32_t destination,
697c7e9729dSAlejandro Lucero 	     unsigned long long address, void *kernel_vaddr, size_t length)
698c7e9729dSAlejandro Lucero {
699c7e9729dSAlejandro Lucero 	struct nfp_cpp_area *area;
700c7e9729dSAlejandro Lucero 	int err;
701c7e9729dSAlejandro Lucero 
702c7e9729dSAlejandro Lucero 	area = nfp_cpp_area_alloc_acquire(cpp, destination, address, length);
703c7e9729dSAlejandro Lucero 	if (!area) {
704c7e9729dSAlejandro Lucero 		printf("Area allocation/acquire failed\n");
705c7e9729dSAlejandro Lucero 		return -1;
706c7e9729dSAlejandro Lucero 	}
707c7e9729dSAlejandro Lucero 
708c7e9729dSAlejandro Lucero 	err = nfp_cpp_area_read(area, 0, kernel_vaddr, length);
709c7e9729dSAlejandro Lucero 
710c7e9729dSAlejandro Lucero 	nfp_cpp_area_release_free(area);
711c7e9729dSAlejandro Lucero 	return err;
712c7e9729dSAlejandro Lucero }
713c7e9729dSAlejandro Lucero 
714c7e9729dSAlejandro Lucero /*
715c7e9729dSAlejandro Lucero  * nfp_cpp_write - write to CPP target
716c7e9729dSAlejandro Lucero  * @cpp:        CPP handle
717c7e9729dSAlejandro Lucero  * @destination:    CPP id
718c7e9729dSAlejandro Lucero  * @address:        offset into CPP target
719c7e9729dSAlejandro Lucero  * @kernel_vaddr:   kernel buffer to read from
720c7e9729dSAlejandro Lucero  * @length:     number of bytes to write
721c7e9729dSAlejandro Lucero  */
722c7e9729dSAlejandro Lucero int
nfp_cpp_write(struct nfp_cpp * cpp,uint32_t destination,unsigned long long address,const void * kernel_vaddr,size_t length)723c7e9729dSAlejandro Lucero nfp_cpp_write(struct nfp_cpp *cpp, uint32_t destination,
724c7e9729dSAlejandro Lucero 	      unsigned long long address, const void *kernel_vaddr,
725c7e9729dSAlejandro Lucero 	      size_t length)
726c7e9729dSAlejandro Lucero {
727c7e9729dSAlejandro Lucero 	struct nfp_cpp_area *area;
728c7e9729dSAlejandro Lucero 	int err;
729c7e9729dSAlejandro Lucero 
730c7e9729dSAlejandro Lucero 	area = nfp_cpp_area_alloc_acquire(cpp, destination, address, length);
731c7e9729dSAlejandro Lucero 	if (!area)
732c7e9729dSAlejandro Lucero 		return -1;
733c7e9729dSAlejandro Lucero 
734c7e9729dSAlejandro Lucero 	err = nfp_cpp_area_write(area, 0, kernel_vaddr, length);
735c7e9729dSAlejandro Lucero 
736c7e9729dSAlejandro Lucero 	nfp_cpp_area_release_free(area);
737c7e9729dSAlejandro Lucero 	return err;
738c7e9729dSAlejandro Lucero }
739c7e9729dSAlejandro Lucero 
740c7e9729dSAlejandro Lucero /*
741c7e9729dSAlejandro Lucero  * nfp_cpp_area_fill - fill a CPP area with a value
742c7e9729dSAlejandro Lucero  * @area:       CPP area
743c7e9729dSAlejandro Lucero  * @offset:     offset into CPP area
744c7e9729dSAlejandro Lucero  * @value:      value to fill with
745c7e9729dSAlejandro Lucero  * @length:     length of area to fill
746c7e9729dSAlejandro Lucero  */
747c7e9729dSAlejandro Lucero int
nfp_cpp_area_fill(struct nfp_cpp_area * area,unsigned long offset,uint32_t value,size_t length)748c7e9729dSAlejandro Lucero nfp_cpp_area_fill(struct nfp_cpp_area *area, unsigned long offset,
749c7e9729dSAlejandro Lucero 		  uint32_t value, size_t length)
750c7e9729dSAlejandro Lucero {
751c7e9729dSAlejandro Lucero 	int err;
752c7e9729dSAlejandro Lucero 	size_t i;
753c7e9729dSAlejandro Lucero 	uint64_t value64;
754c7e9729dSAlejandro Lucero 
755c7e9729dSAlejandro Lucero 	value = rte_cpu_to_le_32(value);
756c7e9729dSAlejandro Lucero 	value64 = ((uint64_t)value << 32) | value;
757c7e9729dSAlejandro Lucero 
758c7e9729dSAlejandro Lucero 	if ((offset + length) > area->size)
759c7e9729dSAlejandro Lucero 		return NFP_ERRNO(EINVAL);
760c7e9729dSAlejandro Lucero 
761c7e9729dSAlejandro Lucero 	if ((area->offset + offset) & 3)
762c7e9729dSAlejandro Lucero 		return NFP_ERRNO(EINVAL);
763c7e9729dSAlejandro Lucero 
764c7e9729dSAlejandro Lucero 	if (((area->offset + offset) & 7) == 4 && length >= 4) {
765c7e9729dSAlejandro Lucero 		err = nfp_cpp_area_write(area, offset, &value, sizeof(value));
766c7e9729dSAlejandro Lucero 		if (err < 0)
767c7e9729dSAlejandro Lucero 			return err;
768c7e9729dSAlejandro Lucero 		if (err != sizeof(value))
769c7e9729dSAlejandro Lucero 			return NFP_ERRNO(ENOSPC);
770c7e9729dSAlejandro Lucero 		offset += sizeof(value);
771c7e9729dSAlejandro Lucero 		length -= sizeof(value);
772c7e9729dSAlejandro Lucero 	}
773c7e9729dSAlejandro Lucero 
774c7e9729dSAlejandro Lucero 	for (i = 0; (i + sizeof(value)) < length; i += sizeof(value64)) {
775c7e9729dSAlejandro Lucero 		err =
776c7e9729dSAlejandro Lucero 		    nfp_cpp_area_write(area, offset + i, &value64,
777c7e9729dSAlejandro Lucero 				       sizeof(value64));
778c7e9729dSAlejandro Lucero 		if (err < 0)
779c7e9729dSAlejandro Lucero 			return err;
780c7e9729dSAlejandro Lucero 		if (err != sizeof(value64))
781c7e9729dSAlejandro Lucero 			return NFP_ERRNO(ENOSPC);
782c7e9729dSAlejandro Lucero 	}
783c7e9729dSAlejandro Lucero 
784c7e9729dSAlejandro Lucero 	if ((i + sizeof(value)) <= length) {
785c7e9729dSAlejandro Lucero 		err =
786c7e9729dSAlejandro Lucero 		    nfp_cpp_area_write(area, offset + i, &value, sizeof(value));
787c7e9729dSAlejandro Lucero 		if (err < 0)
788c7e9729dSAlejandro Lucero 			return err;
789c7e9729dSAlejandro Lucero 		if (err != sizeof(value))
790c7e9729dSAlejandro Lucero 			return NFP_ERRNO(ENOSPC);
791c7e9729dSAlejandro Lucero 		i += sizeof(value);
792c7e9729dSAlejandro Lucero 	}
793c7e9729dSAlejandro Lucero 
794c7e9729dSAlejandro Lucero 	return (int)i;
795c7e9729dSAlejandro Lucero }
796c7e9729dSAlejandro Lucero 
797c7e9729dSAlejandro Lucero /*
798c7e9729dSAlejandro Lucero  * NOTE: This code should not use nfp_xpb_* functions,
799c7e9729dSAlejandro Lucero  * as those are model-specific
800c7e9729dSAlejandro Lucero  */
801c7e9729dSAlejandro Lucero uint32_t
__nfp_cpp_model_autodetect(struct nfp_cpp * cpp,uint32_t * model)802c0a8b024SHeinrich Kuhn __nfp_cpp_model_autodetect(struct nfp_cpp *cpp, uint32_t *model)
803c7e9729dSAlejandro Lucero {
804c0a8b024SHeinrich Kuhn 	uint32_t reg;
805c0a8b024SHeinrich Kuhn 	int err;
806c7e9729dSAlejandro Lucero 
807c0a8b024SHeinrich Kuhn 	err = nfp_xpb_readl(cpp, NFP_XPB_DEVICE(1, 1, 16) + NFP_PL_DEVICE_ID,
808c0a8b024SHeinrich Kuhn 			    &reg);
809c0a8b024SHeinrich Kuhn 	if (err < 0)
810c0a8b024SHeinrich Kuhn 		return err;
811c0a8b024SHeinrich Kuhn 
812c0a8b024SHeinrich Kuhn 	*model = reg & NFP_PL_DEVICE_MODEL_MASK;
813c0a8b024SHeinrich Kuhn 	if (*model & NFP_PL_DEVICE_ID_MASK)
814c0a8b024SHeinrich Kuhn 		*model -= 0x10;
815c0a8b024SHeinrich Kuhn 
8160fec453dSAlejandro Lucero 	return 0;
817c7e9729dSAlejandro Lucero }
818c7e9729dSAlejandro Lucero 
819c7e9729dSAlejandro Lucero /*
820c7e9729dSAlejandro Lucero  * nfp_cpp_map_area() - Helper function to map an area
821c7e9729dSAlejandro Lucero  * @cpp:    NFP CPP handler
822c7e9729dSAlejandro Lucero  * @domain: CPP domain
823c7e9729dSAlejandro Lucero  * @target: CPP target
824c7e9729dSAlejandro Lucero  * @addr:   CPP address
825c7e9729dSAlejandro Lucero  * @size:   Size of the area
826c7e9729dSAlejandro Lucero  * @area:   Area handle (output)
827c7e9729dSAlejandro Lucero  *
828c7e9729dSAlejandro Lucero  * Map an area of IOMEM access.  To undo the effect of this function call
829c7e9729dSAlejandro Lucero  * @nfp_cpp_area_release_free(*area).
830c7e9729dSAlejandro Lucero  *
831c7e9729dSAlejandro Lucero  * Return: Pointer to memory mapped area or ERR_PTR
832c7e9729dSAlejandro Lucero  */
833c7e9729dSAlejandro Lucero uint8_t *
nfp_cpp_map_area(struct nfp_cpp * cpp,int domain,int target,uint64_t addr,unsigned long size,struct nfp_cpp_area ** area)834c7e9729dSAlejandro Lucero nfp_cpp_map_area(struct nfp_cpp *cpp, int domain, int target, uint64_t addr,
835c7e9729dSAlejandro Lucero 		 unsigned long size, struct nfp_cpp_area **area)
836c7e9729dSAlejandro Lucero {
837c7e9729dSAlejandro Lucero 	uint8_t *res;
838c7e9729dSAlejandro Lucero 	uint32_t dest;
839c7e9729dSAlejandro Lucero 
840c7e9729dSAlejandro Lucero 	dest = NFP_CPP_ISLAND_ID(target, NFP_CPP_ACTION_RW, 0, domain);
841c7e9729dSAlejandro Lucero 
842c7e9729dSAlejandro Lucero 	*area = nfp_cpp_area_alloc_acquire(cpp, dest, addr, size);
843c7e9729dSAlejandro Lucero 	if (!*area)
844c7e9729dSAlejandro Lucero 		goto err_eio;
845c7e9729dSAlejandro Lucero 
846c7e9729dSAlejandro Lucero 	res = nfp_cpp_area_iomem(*area);
847c7e9729dSAlejandro Lucero 	if (!res)
848c7e9729dSAlejandro Lucero 		goto err_release_free;
849c7e9729dSAlejandro Lucero 
850c7e9729dSAlejandro Lucero 	return res;
851c7e9729dSAlejandro Lucero 
852c7e9729dSAlejandro Lucero err_release_free:
853c7e9729dSAlejandro Lucero 	nfp_cpp_area_release_free(*area);
854c7e9729dSAlejandro Lucero err_eio:
855c7e9729dSAlejandro Lucero 	return NULL;
856c7e9729dSAlejandro Lucero }
857