aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/nfp/nfpcore/nfp_cpp.h
blob: 1427954c173c1b23537deeac12f4d20c4bea0c4f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
/* SPDX-License-Identifier: BSD-3-Clause
 * Copyright(c) 2018 Netronome Systems, Inc.
 * All rights reserved.
 */

#ifndef __NFP_CPP_H__
#define __NFP_CPP_H__

#include <rte_ethdev_pci.h>

#include "nfp-common/nfp_platform.h"
#include "nfp-common/nfp_resid.h"

struct nfp_cpp_mutex;

/*
 * NFP CPP handle
 */
struct nfp_cpp {
	uint32_t model;
	uint32_t interface;
	uint8_t *serial;
	int serial_len;
	void *priv;

	/* Mutex cache */
	struct nfp_cpp_mutex *mutex_cache;
	const struct nfp_cpp_operations *op;

	/*
	 * NFP-6xxx originating island IMB CPP Address Translation. CPP Target
	 * ID is index into array. Values are obtained at runtime from local
	 * island XPB CSRs.
	 */
	uint32_t imb_cat_table[16];

	int driver_lock_needed;
};

/*
 * NFP CPP device area handle
 */
struct nfp_cpp_area {
	struct nfp_cpp *cpp;
	char *name;
	unsigned long long offset;
	unsigned long size;
	/* Here follows the 'priv' part of nfp_cpp_area. */
};

/*
 * NFP CPP operations structure
 */
struct nfp_cpp_operations {
	/* Size of priv area in struct nfp_cpp_area */
	size_t area_priv_size;

	/* Instance an NFP CPP */
	int (*init)(struct nfp_cpp *cpp, struct rte_pci_device *dev);

	/*
	 * Free the bus.
	 * Called only once, during nfp_cpp_unregister()
	 */
	void (*free)(struct nfp_cpp *cpp);

	/*
	 * Initialize a new NFP CPP area
	 * NOTE: This is _not_ serialized
	 */
	int (*area_init)(struct nfp_cpp_area *area,
			 uint32_t dest,
			 unsigned long long address,
			 unsigned long size);
	/*
	 * Clean up a NFP CPP area before it is freed
	 * NOTE: This is _not_ serialized
	 */
	void (*area_cleanup)(struct nfp_cpp_area *area);

	/*
	 * Acquire resources for a NFP CPP area
	 * Serialized
	 */
	int (*area_acquire)(struct nfp_cpp_area *area);
	/*
	 * Release resources for a NFP CPP area
	 * Serialized
	 */
	void (*area_release)(struct nfp_cpp_area *area);
	/*
	 * Return a void IO pointer to a NFP CPP area
	 * NOTE: This is _not_ serialized
	 */

	void *(*area_iomem)(struct nfp_cpp_area *area);

	void *(*area_mapped)(struct nfp_cpp_area *area);
	/*
	 * Perform a read from a NFP CPP area
	 * Serialized
	 */
	int (*area_read)(struct nfp_cpp_area *area,
			 void *kernel_vaddr,
			 unsigned long offset,
			 unsigned int length);
	/*
	 * Perform a write to a NFP CPP area
	 * Serialized
	 */
	int (*area_write)(struct nfp_cpp_area *area,
			  const void *kernel_vaddr,
			  unsigned long offset,
			  unsigned int length);
};

/*
 * This should be the only external function the transport
 * module supplies
 */
const struct nfp_cpp_operations *nfp_cpp_transport_operations(void);

/*
 * Set the model id
 *
 * @param   cpp     NFP CPP operations structure
 * @param   model   Model ID
 */
void nfp_cpp_model_set(struct nfp_cpp *cpp, uint32_t model);

/*
 * Set the private instance owned data of a nfp_cpp struct
 *
 * @param   cpp     NFP CPP operations structure
 * @param   interface Interface ID
 */
void nfp_cpp_interface_set(struct nfp_cpp *cpp, uint32_t interface);

/*
 * Set the private instance owned data of a nfp_cpp struct
 *
 * @param   cpp     NFP CPP operations structure
 * @param   serial  NFP serial byte array
 * @param   len     Length of the serial byte array
 */
int nfp_cpp_serial_set(struct nfp_cpp *cpp, const uint8_t *serial,
		       size_t serial_len);

/*
 * Set the private data of the nfp_cpp instance
 *
 * @param   cpp NFP CPP operations structure
 * @return      Opaque device pointer
 */
void nfp_cpp_priv_set(struct nfp_cpp *cpp, void *priv);

/*
 * Return the private data of the nfp_cpp instance
 *
 * @param   cpp NFP CPP operations structure
 * @return      Opaque device pointer
 */
void *nfp_cpp_priv(struct nfp_cpp *cpp);

/*
 * Get the privately allocated portion of a NFP CPP area handle
 *
 * @param   cpp_area    NFP CPP area handle
 * @return          Pointer to the private area, or NULL on failure
 */
void *nfp_cpp_area_priv(struct nfp_cpp_area *cpp_area);

uint32_t __nfp_cpp_model_autodetect(struct nfp_cpp *cpp);

/*
 * NFP CPP core interface for CPP clients.
 */

/*
 * Open a NFP CPP handle to a CPP device
 *
 * @param[in]	id	0-based ID for the CPP interface to use
 *
 * @return NFP CPP handle, or NULL on failure (and set errno accordingly).
 */
struct nfp_cpp *nfp_cpp_from_device_name(struct rte_pci_device *dev,
					 int driver_lock_needed);

/*
 * Free a NFP CPP handle
 *
 * @param[in]	cpp	NFP CPP handle
 */
void nfp_cpp_free(struct nfp_cpp *cpp);

#define NFP_CPP_MODEL_INVALID   0xffffffff

/*
 * NFP_CPP_MODEL_CHIP_of - retrieve the chip ID from the model ID
 *
 * The chip ID is a 16-bit BCD+A-F encoding for the chip type.
 *
 * @param[in]   model   NFP CPP model id
 * @return      NFP CPP chip id
 */
#define NFP_CPP_MODEL_CHIP_of(model)        (((model) >> 16) & 0xffff)

/*
 * NFP_CPP_MODEL_IS_6000 - Check for the NFP6000 family of devices
 *
 * NOTE: The NFP4000 series is considered as a NFP6000 series variant.
 *
 * @param[in]	model	NFP CPP model id
 * @return		true if model is in the NFP6000 family, false otherwise.
 */
#define NFP_CPP_MODEL_IS_6000(model)		     \
		((NFP_CPP_MODEL_CHIP_of(model) >= 0x4000) && \
		(NFP_CPP_MODEL_CHIP_of(model) < 0x7000))

/*
 * nfp_cpp_model - Retrieve the Model ID of the NFP
 *
 * @param[in]	cpp	NFP CPP handle
 * @return		NFP CPP Model ID
 */
uint32_t nfp_cpp_model(struct nfp_cpp *cpp);

/*
 * NFP Interface types - logical interface for this CPP connection 4 bits are
 * reserved for interface type.
 */
#define NFP_CPP_INTERFACE_TYPE_INVALID		0x0
#define NFP_CPP_INTERFACE_TYPE_PCI		0x1
#define NFP_CPP_INTERFACE_TYPE_ARM		0x2
#define NFP_CPP_INTERFACE_TYPE_RPC		0x3
#define NFP_CPP_INTERFACE_TYPE_ILA		0x4

/*
 * Construct a 16-bit NFP Interface ID
 *
 * Interface IDs consists of 4 bits of interface type, 4 bits of unit
 * identifier, and 8 bits of channel identifier.
 *
 * The NFP Interface ID is used in the implementation of NFP CPP API mutexes,
 * which use the MU Atomic CompareAndWrite operation - hence the limit to 16
 * bits to be able to use the NFP Interface ID as a lock owner.
 *
 * @param[in]	type	NFP Interface Type
 * @param[in]	unit	Unit identifier for the interface type
 * @param[in]	channel	Channel identifier for the interface unit
 * @return		Interface ID
 */
#define NFP_CPP_INTERFACE(type, unit, channel)	\
	((((type) & 0xf) << 12) | \
	 (((unit) & 0xf) <<  8) | \
	 (((channel) & 0xff) << 0))

/*
 * Get the interface type of a NFP Interface ID
 * @param[in]	interface	NFP Interface ID
 * @return			NFP Interface ID's type
 */
#define NFP_CPP_INTERFACE_TYPE_of(interface)	(((interface) >> 12) & 0xf)

/*
 * Get the interface unit of a NFP Interface ID
 * @param[in]	interface	NFP Interface ID
 * @return			NFP Interface ID's unit
 */
#define NFP_CPP_INTERFACE_UNIT_of(interface)	(((interface) >>  8) & 0xf)

/*
 * Get the interface channel of a NFP Interface ID
 * @param[in]	interface	NFP Interface ID
 * @return			NFP Interface ID's channel
 */
#define NFP_CPP_INTERFACE_CHANNEL_of(interface)	(((interface) >>  0) & 0xff)

/*
 * Retrieve the Interface ID of the NFP
 * @param[in]	cpp	NFP CPP handle
 * @return		NFP CPP Interface ID
 */
uint16_t nfp_cpp_interface(struct nfp_cpp *cpp);

/*
 * Retrieve the NFP Serial Number (unique per NFP)
 * @param[in]	cpp	NFP CPP handle
 * @param[out]	serial	Pointer to reference the serial number array
 *
 * @return	size of the NFP6000 serial number, in bytes
 */
int nfp_cpp_serial(struct nfp_cpp *cpp, const uint8_t **serial);

/*
 * Allocate a NFP CPP area handle, as an offset into a CPP ID
 * @param[in]	cpp	NFP CPP handle
 * @param[in]	cpp_id	NFP CPP ID
 * @param[in]	address	Offset into the NFP CPP ID address space
 * @param[in]	size	Size of the area to reserve
 *
 * @return NFP CPP handle, or NULL on failure (and set errno accordingly).
 */
struct nfp_cpp_area *nfp_cpp_area_alloc(struct nfp_cpp *cpp, uint32_t cpp_id,
					unsigned long long address,
					unsigned long size);

/*
 * Allocate a NFP CPP area handle, as an offset into a CPP ID, by a named owner
 * @param[in]	cpp	NFP CPP handle
 * @param[in]	cpp_id	NFP CPP ID
 * @param[in]	name	Name of owner of the area
 * @param[in]	address	Offset into the NFP CPP ID address space
 * @param[in]	size	Size of the area to reserve
 *
 * @return NFP CPP handle, or NULL on failure (and set errno accordingly).
 */
struct nfp_cpp_area *nfp_cpp_area_alloc_with_name(struct nfp_cpp *cpp,
						  uint32_t cpp_id,
						  const char *name,
						  unsigned long long address,
						  unsigned long size);

/*
 * Free an allocated NFP CPP area handle
 * @param[in]	area	NFP CPP area handle
 */
void nfp_cpp_area_free(struct nfp_cpp_area *area);

/*
 * Acquire the resources needed to access the NFP CPP area handle
 *
 * @param[in]	area	NFP CPP area handle
 *
 * @return 0 on success, -1 on failure (and set errno accordingly).
 */
int nfp_cpp_area_acquire(struct nfp_cpp_area *area);

/*
 * Release the resources needed to access the NFP CPP area handle
 *
 * @param[in]	area	NFP CPP area handle
 */
void nfp_cpp_area_release(struct nfp_cpp_area *area);

/*
 * Allocate, then acquire the resources needed to access the NFP CPP area handle
 * @param[in]	cpp	NFP CPP handle
 * @param[in]	cpp_id	NFP CPP ID
 * @param[in]	address	Offset into the NFP CPP ID address space
 * @param[in]	size	Size of the area to reserve
 *
 * @return NFP CPP handle, or NULL on failure (and set errno accordingly).
 */
struct nfp_cpp_area *nfp_cpp_area_alloc_acquire(struct nfp_cpp *cpp,
						uint32_t cpp_id,
						unsigned long long address,
						unsigned long size);

/*
 * Release the resources, then free the NFP CPP area handle
 * @param[in]	area	NFP CPP area handle
 */
void nfp_cpp_area_release_free(struct nfp_cpp_area *area);

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);
/*
 * Return an IO pointer to the beginning of the NFP CPP area handle. The area
 * must be acquired with 'nfp_cpp_area_acquire()' before calling this operation.
 *
 * @param[in]	area	NFP CPP area handle
 *
 * @return Pointer to IO memory, or NULL on failure (and set errno accordingly).
 */
void *nfp_cpp_area_mapped(struct nfp_cpp_area *area);

/*
 * Read from a NFP CPP area handle into a buffer. The area must be acquired with
 * 'nfp_cpp_area_acquire()' before calling this operation.
 *
 * @param[in]	area	NFP CPP area handle
 * @param[in]	offset	Offset into the area
 * @param[in]	buffer	Location of buffer to receive the data
 * @param[in]	length	Length of the data to read
 *
 * @return bytes read on success, -1 on failure (and set errno accordingly).
 *
 */
int nfp_cpp_area_read(struct nfp_cpp_area *area, unsigned long offset,
		      void *buffer, size_t length);

/*
 * Write to a NFP CPP area handle from a buffer. The area must be acquired with
 * 'nfp_cpp_area_acquire()' before calling this operation.
 *
 * @param[in]	area	NFP CPP area handle
 * @param[in]	offset	Offset into the area
 * @param[in]	buffer	Location of buffer that holds the data
 * @param[in]	length	Length of the data to read
 *
 * @return bytes written on success, -1 on failure (and set errno accordingly).
 */
int nfp_cpp_area_write(struct nfp_cpp_area *area, unsigned long offset,
		       const void *buffer, size_t length);

/*
 * nfp_cpp_area_iomem() - get IOMEM region for CPP area
 * @area:       CPP area handle
 *
 * Returns an iomem pointer for use with readl()/writel() style operations.
 *
 * NOTE: Area must have been locked down with an 'acquire'.
 *
 * Return: pointer to the area, or NULL
 */
void *nfp_cpp_area_iomem(struct nfp_cpp_area *area);

/*
 * Verify that IO can be performed on an offset in an area
 *
 * @param[in]	area	NFP CPP area handle
 * @param[in]	offset	Offset into the area
 * @param[in]	size	Size of region to validate
 *
 * @return 0 on success, -1 on failure (and set errno accordingly).
 */
int nfp_cpp_area_check_range(struct nfp_cpp_area *area,
			     unsigned long long offset, unsigned long size);

/*
 * Get the NFP CPP handle that is the parent of a NFP CPP area handle
 *
 * @param	cpp_area	NFP CPP area handle
 * @return			NFP CPP handle
 */
struct nfp_cpp *nfp_cpp_area_cpp(struct nfp_cpp_area *cpp_area);

/*
 * Get the name passed during allocation of the NFP CPP area handle
 *
 * @param	cpp_area	NFP CPP area handle
 * @return			Pointer to the area's name
 */
const char *nfp_cpp_area_name(struct nfp_cpp_area *cpp_area);

/*
 * Read a block of data from a NFP CPP ID
 *
 * @param[in]	cpp	NFP CPP handle
 * @param[in]	cpp_id	NFP CPP ID
 * @param[in]	address	Offset into the NFP CPP ID address space
 * @param[in]	kernel_vaddr	Buffer to copy read data to
 * @param[in]	length	Size of the area to reserve
 *
 * @return bytes read on success, -1 on failure (and set errno accordingly).
 */
int nfp_cpp_read(struct nfp_cpp *cpp, uint32_t cpp_id,
		 unsigned long long address, void *kernel_vaddr, size_t length);

/*
 * Write a block of data to a NFP CPP ID
 *
 * @param[in]	cpp	NFP CPP handle
 * @param[in]	cpp_id	NFP CPP ID
 * @param[in]	address	Offset into the NFP CPP ID address space
 * @param[in]	kernel_vaddr	Buffer to copy write data from
 * @param[in]	length	Size of the area to reserve
 *
 * @return bytes written on success, -1 on failure (and set errno accordingly).
 */
int nfp_cpp_write(struct nfp_cpp *cpp, uint32_t cpp_id,
		  unsigned long long address, const void *kernel_vaddr,
		  size_t length);



/*
 * Fill a NFP CPP area handle and offset with a value
 *
 * @param[in]	area	NFP CPP area handle
 * @param[in]	offset	Offset into the NFP CPP ID address space
 * @param[in]	value	32-bit value to fill area with
 * @param[in]	length	Size of the area to reserve
 *
 * @return bytes written on success, -1 on failure (and set errno accordingly).
 */
int nfp_cpp_area_fill(struct nfp_cpp_area *area, unsigned long offset,
		      uint32_t value, size_t length);

/*
 * Read a single 32-bit value from a NFP CPP area handle
 *
 * @param area		NFP CPP area handle
 * @param offset	offset into NFP CPP area handle
 * @param value		output value
 *
 * The area must be acquired with 'nfp_cpp_area_acquire()' before calling this
 * operation.
 *
 * NOTE: offset must be 32-bit aligned.
 *
 * @return 0 on success, or -1 on error (and set errno accordingly).
 */
int nfp_cpp_area_readl(struct nfp_cpp_area *area, unsigned long offset,
		       uint32_t *value);

/*
 * Write a single 32-bit value to a NFP CPP area handle
 *
 * @param area		NFP CPP area handle
 * @param offset	offset into NFP CPP area handle
 * @param value		value to write
 *
 * The area must be acquired with 'nfp_cpp_area_acquire()' before calling this
 * operation.
 *
 * NOTE: offset must be 32-bit aligned.
 *
 * @return 0 on success, or -1 on error (and set errno accordingly).
 */
int nfp_cpp_area_writel(struct nfp_cpp_area *area, unsigned long offset,
			uint32_t value);

/*
 * Read a single 64-bit value from a NFP CPP area handle
 *
 * @param area		NFP CPP area handle
 * @param offset	offset into NFP CPP area handle
 * @param value		output value
 *
 * The area must be acquired with 'nfp_cpp_area_acquire()' before calling this
 * operation.
 *
 * NOTE: offset must be 64-bit aligned.
 *
 * @return 0 on success, or -1 on error (and set errno accordingly).
 */
int nfp_cpp_area_readq(struct nfp_cpp_area *area, unsigned long offset,
		       uint64_t *value);

/*
 * Write a single 64-bit value to a NFP CPP area handle
 *
 * @param area		NFP CPP area handle
 * @param offset	offset into NFP CPP area handle
 * @param value		value to write
 *
 * The area must be acquired with 'nfp_cpp_area_acquire()' before calling this
 * operation.
 *
 * NOTE: offset must be 64-bit aligned.
 *
 * @return 0 on success, or -1 on error (and set errno accordingly).
 */
int nfp_cpp_area_writeq(struct nfp_cpp_area *area, unsigned long offset,
			uint64_t value);

/*
 * Write a single 32-bit value on the XPB bus
 *
 * @param cpp           NFP CPP device handle
 * @param xpb_tgt	XPB target and address
 * @param value         value to write
 *
 * @return 0 on success, or -1 on failure (and set errno accordingly).
 */
int nfp_xpb_writel(struct nfp_cpp *cpp, uint32_t xpb_tgt, uint32_t value);

/*
 * Read a single 32-bit value from the XPB bus
 *
 * @param cpp           NFP CPP device handle
 * @param xpb_tgt	XPB target and address
 * @param value         output value
 *
 * @return 0 on success, or -1 on failure (and set errno accordingly).
 */
int nfp_xpb_readl(struct nfp_cpp *cpp, uint32_t xpb_tgt, uint32_t *value);

/*
 * Modify bits of a 32-bit value from the XPB bus
 *
 * @param cpp           NFP CPP device handle
 * @param xpb_tgt       XPB target and address
 * @param mask          mask of bits to alter
 * @param value         value to modify
 *
 * @return 0 on success, or -1 on failure (and set errno accordingly).
 */
int nfp_xpb_writelm(struct nfp_cpp *cpp, uint32_t xpb_tgt, uint32_t mask,
		    uint32_t value);

/*
 * Modify bits of a 32-bit value from the XPB bus
 *
 * @param cpp           NFP CPP device handle
 * @param xpb_tgt       XPB target and address
 * @param mask          mask of bits to alter
 * @param value         value to monitor for
 * @param timeout_us    maximum number of us to wait (-1 for forever)
 *
 * @return >= 0 on success, or -1 on failure (and set errno accordingly).
 */
int nfp_xpb_waitlm(struct nfp_cpp *cpp, uint32_t xpb_tgt, uint32_t mask,
		   uint32_t value, int timeout_us);

/*
 * Read a 32-bit word from a NFP CPP ID
 *
 * @param cpp           NFP CPP handle
 * @param cpp_id        NFP CPP ID
 * @param address       offset into the NFP CPP ID address space
 * @param value         output value
 *
 * @return 0 on success, or -1 on failure (and set errno accordingly).
 */
int nfp_cpp_readl(struct nfp_cpp *cpp, uint32_t cpp_id,
		  unsigned long long address, uint32_t *value);

/*
 * Write a 32-bit value to a NFP CPP ID
 *
 * @param cpp           NFP CPP handle
 * @param cpp_id        NFP CPP ID
 * @param address       offset into the NFP CPP ID address space
 * @param value         value to write
 *
 * @return 0 on success, or -1 on failure (and set errno accordingly).
 *
 */
int nfp_cpp_writel(struct nfp_cpp *cpp, uint32_t cpp_id,
		   unsigned long long address, uint32_t value);

/*
 * Read a 64-bit work from a NFP CPP ID
 *
 * @param cpp           NFP CPP handle
 * @param cpp_id        NFP CPP ID
 * @param address       offset into the NFP CPP ID address space
 * @param value         output value
 *
 * @return 0 on success, or -1 on failure (and set errno accordingly).
 */
int nfp_cpp_readq(struct nfp_cpp *cpp, uint32_t cpp_id,
		  unsigned long long address, uint64_t *value);

/*
 * Write a 64-bit value to a NFP CPP ID
 *
 * @param cpp           NFP CPP handle
 * @param cpp_id        NFP CPP ID
 * @param address       offset into the NFP CPP ID address space
 * @param value         value to write
 *
 * @return 0 on success, or -1 on failure (and set errno accordingly).
 */
int nfp_cpp_writeq(struct nfp_cpp *cpp, uint32_t cpp_id,
		   unsigned long long address, uint64_t value);

/*
 * Initialize a mutex location

 * The CPP target:address must point to a 64-bit aligned location, and will
 * initialize 64 bits of data at the location.
 *
 * This creates the initial mutex state, as locked by this nfp_cpp_interface().
 *
 * This function should only be called when setting up the initial lock state
 * upon boot-up of the system.
 *
 * @param cpp		NFP CPP handle
 * @param target	NFP CPP target ID
 * @param address	Offset into the address space of the NFP CPP target ID
 * @param key_id	Unique 32-bit value for this mutex
 *
 * @return 0 on success, or -1 on failure (and set errno accordingly).
 */
int nfp_cpp_mutex_init(struct nfp_cpp *cpp, int target,
		       unsigned long long address, uint32_t key_id);

/*
 * Create a mutex handle from an address controlled by a MU Atomic engine
 *
 * The CPP target:address must point to a 64-bit aligned location, and reserve
 * 64 bits of data at the location for use by the handle.
 *
 * Only target/address pairs that point to entities that support the MU Atomic
 * Engine's CmpAndSwap32 command are supported.
 *
 * @param cpp		NFP CPP handle
 * @param target	NFP CPP target ID
 * @param address	Offset into the address space of the NFP CPP target ID
 * @param key_id	32-bit unique key (must match the key at this location)
 *
 * @return		A non-NULL struct nfp_cpp_mutex * on success, NULL on
 *                      failure.
 */
struct nfp_cpp_mutex *nfp_cpp_mutex_alloc(struct nfp_cpp *cpp, int target,
					  unsigned long long address,
					  uint32_t key_id);

/*
 * Get the NFP CPP handle the mutex was created with
 *
 * @param   mutex   NFP mutex handle
 * @return          NFP CPP handle
 */
struct nfp_cpp *nfp_cpp_mutex_cpp(struct nfp_cpp_mutex *mutex);

/*
 * Get the mutex key
 *
 * @param   mutex   NFP mutex handle
 * @return          Mutex key
 */
uint32_t nfp_cpp_mutex_key(struct nfp_cpp_mutex *mutex);

/*
 * Get the mutex owner
 *
 * @param   mutex   NFP mutex handle
 * @return          Interface ID of the mutex owner
 *
 * NOTE: This is for debug purposes ONLY - the owner may change at any time,
 * unless it has been locked by this NFP CPP handle.
 */
uint16_t nfp_cpp_mutex_owner(struct nfp_cpp_mutex *mutex);

/*
 * Get the mutex target
 *
 * @param   mutex   NFP mutex handle
 * @return          Mutex CPP target (ie NFP_CPP_TARGET_MU)
 */
int nfp_cpp_mutex_target(struct nfp_cpp_mutex *mutex);

/*
 * Get the mutex address
 *
 * @param   mutex   NFP mutex handle
 * @return          Mutex CPP address
 */
uint64_t nfp_cpp_mutex_address(struct nfp_cpp_mutex *mutex);

/*
 * Free a mutex handle - does not alter the lock state
 *
 * @param mutex		NFP CPP Mutex handle
 */
void nfp_cpp_mutex_free(struct nfp_cpp_mutex *mutex);

/*
 * Lock a mutex handle, using the NFP MU Atomic Engine
 *
 * @param mutex		NFP CPP Mutex handle
 *
 * @return 0 on success, or -1 on failure (and set errno accordingly).
 */
int nfp_cpp_mutex_lock(struct nfp_cpp_mutex *mutex);

/*
 * Unlock a mutex handle, using the NFP MU Atomic Engine
 *
 * @param mutex		NFP CPP Mutex handle
 *
 * @return 0 on success, or -1 on failure (and set errno accordingly).
 */
int nfp_cpp_mutex_unlock(struct nfp_cpp_mutex *mutex);

/*
 * Attempt to lock a mutex handle, using the NFP MU Atomic Engine
 *
 * @param mutex		NFP CPP Mutex handle
 * @return		0 if the lock succeeded, -1 on failure (and errno set
 *			appropriately).
 */
int nfp_cpp_mutex_trylock(struct nfp_cpp_mutex *mutex);

#endif /* !__NFP_CPP_H__ */