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 ®);
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