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