New upstream version 18.05
[deb_dpdk.git] / drivers / net / nfp / nfpcore / nfp-common / nfp_cppat.h
diff --git a/drivers/net/nfp/nfpcore/nfp-common/nfp_cppat.h b/drivers/net/nfp/nfpcore/nfp-common/nfp_cppat.h
new file mode 100644 (file)
index 0000000..6e380cc
--- /dev/null
@@ -0,0 +1,722 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Netronome Systems, Inc.
+ * All rights reserved.
+ */
+
+#ifndef __NFP_CPPAT_H__
+#define __NFP_CPPAT_H__
+
+#include "nfp_platform.h"
+#include "nfp_resid.h"
+
+/* This file contains helpers for creating CPP commands
+ *
+ * All magic NFP-6xxx IMB 'mode' numbers here are from:
+ * Databook (1 August 2013)
+ * - System Overview and Connectivity
+ * -- Internal Connectivity
+ * --- Distributed Switch Fabric - Command Push/Pull (DSF-CPP) Bus
+ * ---- CPP addressing
+ * ----- Table 3.6. CPP Address Translation Mode Commands
+ */
+
+#define _NIC_NFP6000_MU_LOCALITY_DIRECT 2
+
+static inline int
+_nfp6000_decode_basic(uint64_t addr, int *dest_island, int cpp_tgt, int mode,
+                     int addr40, int isld1, int isld0);
+
+static uint64_t
+_nic_mask64(int msb, int lsb, int at0)
+{
+       uint64_t v;
+       int w = msb - lsb + 1;
+
+       if (w == 64)
+               return ~(uint64_t)0;
+
+       if ((lsb + w) > 64)
+               return 0;
+
+       v = (UINT64_C(1) << w) - 1;
+
+       if (at0)
+               return v;
+
+       return v << lsb;
+}
+
+/* For VQDR, we may not modify the Channel bits, which might overlap
+ * with the Index bit. When it does, we need to ensure that isld0 == isld1.
+ */
+static inline int
+_nfp6000_encode_basic(uint64_t *addr, int dest_island, int cpp_tgt, int mode,
+                     int addr40, int isld1, int isld0)
+{
+       uint64_t _u64;
+       int iid_lsb, idx_lsb;
+       int i, v = 0;
+       int isld[2];
+
+       isld[0] = isld0;
+       isld[1] = isld1;
+
+       switch (cpp_tgt) {
+       case NFP6000_CPPTGT_MU:
+               /* This function doesn't handle MU */
+               return NFP_ERRNO(EINVAL);
+       case NFP6000_CPPTGT_CTXPB:
+               /* This function doesn't handle CTXPB */
+               return NFP_ERRNO(EINVAL);
+       default:
+               break;
+       }
+
+       switch (mode) {
+       case 0:
+               if (cpp_tgt == NFP6000_CPPTGT_VQDR && !addr40) {
+                       /*
+                        * In this specific mode we'd rather not modify the
+                        * address but we can verify if the existing contents
+                        * will point to a valid island.
+                        */
+                       i = _nfp6000_decode_basic(*addr, &v, cpp_tgt, mode,
+                                                 addr40, isld1,
+                                                 isld0);
+                       if (i != 0)
+                               /* Full Island ID and channel bits overlap */
+                               return i;
+
+                       /*
+                        * If dest_island is invalid, the current address won't
+                        * go where expected.
+                        */
+                       if (dest_island != -1 && dest_island != v)
+                               return NFP_ERRNO(EINVAL);
+
+                       /* If dest_island was -1, we don't care */
+                       return 0;
+               }
+
+               iid_lsb = (addr40) ? 34 : 26;
+
+               /* <39:34> or <31:26> */
+               _u64 = _nic_mask64((iid_lsb + 5), iid_lsb, 0);
+               *addr &= ~_u64;
+               *addr |= (((uint64_t)dest_island) << iid_lsb) & _u64;
+               return 0;
+       case 1:
+               if (cpp_tgt == NFP6000_CPPTGT_VQDR && !addr40) {
+                       i = _nfp6000_decode_basic(*addr, &v, cpp_tgt, mode,
+                                                 addr40, isld1, isld0);
+                       if (i != 0)
+                               /* Full Island ID and channel bits overlap */
+                               return i;
+
+                       /*
+                        * If dest_island is invalid, the current address won't
+                        * go where expected.
+                        */
+                       if (dest_island != -1 && dest_island != v)
+                               return NFP_ERRNO(EINVAL);
+
+                       /* If dest_island was -1, we don't care */
+                       return 0;
+               }
+
+               idx_lsb = (addr40) ? 39 : 31;
+               if (dest_island == isld0) {
+                       /* Only need to clear the Index bit */
+                       *addr &= ~_nic_mask64(idx_lsb, idx_lsb, 0);
+                       return 0;
+               }
+
+               if (dest_island == isld1) {
+                       /* Only need to set the Index bit */
+                       *addr |= (UINT64_C(1) << idx_lsb);
+                       return 0;
+               }
+
+               return NFP_ERRNO(ENODEV);
+       case 2:
+               if (cpp_tgt == NFP6000_CPPTGT_VQDR && !addr40) {
+                       /* iid<0> = addr<30> = channel<0> */
+                       /* channel<1> = addr<31> = Index */
+
+                       /*
+                        * Special case where we allow channel bits to be set
+                        * before hand and with them select an island.
+                        * So we need to confirm that it's at least plausible.
+                        */
+                       i = _nfp6000_decode_basic(*addr, &v, cpp_tgt, mode,
+                                                 addr40, isld1, isld0);
+                       if (i != 0)
+                               /* Full Island ID and channel bits overlap */
+                               return i;
+
+                       /*
+                        * If dest_island is invalid, the current address won't
+                        * go where expected.
+                        */
+                       if (dest_island != -1 && dest_island != v)
+                               return NFP_ERRNO(EINVAL);
+
+                       /* If dest_island was -1, we don't care */
+                       return 0;
+               }
+
+               /*
+                * Make sure we compare against isldN values by clearing the
+                * LSB. This is what the silicon does.
+                **/
+               isld[0] &= ~1;
+               isld[1] &= ~1;
+
+               idx_lsb = (addr40) ? 39 : 31;
+               iid_lsb = idx_lsb - 1;
+
+               /*
+                * Try each option, take first one that fits. Not sure if we
+                * would want to do some smarter searching and prefer 0 or non-0
+                * island IDs.
+                */
+
+               for (i = 0; i < 2; i++) {
+                       for (v = 0; v < 2; v++) {
+                               if (dest_island != (isld[i] | v))
+                                       continue;
+                               *addr &= ~_nic_mask64(idx_lsb, iid_lsb, 0);
+                               *addr |= (((uint64_t)i) << idx_lsb);
+                               *addr |= (((uint64_t)v) << iid_lsb);
+                               return 0;
+                       }
+               }
+
+               return NFP_ERRNO(ENODEV);
+       case 3:
+               if (cpp_tgt == NFP6000_CPPTGT_VQDR && !addr40) {
+                       /*
+                        * iid<0> = addr<29> = data
+                        * iid<1> = addr<30> = channel<0>
+                        * channel<1> = addr<31> = Index
+                        */
+                       i = _nfp6000_decode_basic(*addr, &v, cpp_tgt, mode,
+                                                 addr40, isld1, isld0);
+                       if (i != 0)
+                               /* Full Island ID and channel bits overlap */
+                               return i;
+
+                       if (dest_island != -1 && dest_island != v)
+                               return NFP_ERRNO(EINVAL);
+
+                       /* If dest_island was -1, we don't care */
+                       return 0;
+               }
+
+               isld[0] &= ~3;
+               isld[1] &= ~3;
+
+               idx_lsb = (addr40) ? 39 : 31;
+               iid_lsb = idx_lsb - 2;
+
+               for (i = 0; i < 2; i++) {
+                       for (v = 0; v < 4; v++) {
+                               if (dest_island != (isld[i] | v))
+                                       continue;
+                               *addr &= ~_nic_mask64(idx_lsb, iid_lsb, 0);
+                               *addr |= (((uint64_t)i) << idx_lsb);
+                               *addr |= (((uint64_t)v) << iid_lsb);
+                               return 0;
+                       }
+               }
+               return NFP_ERRNO(ENODEV);
+       default:
+               break;
+       }
+
+       return NFP_ERRNO(EINVAL);
+}
+
+static inline int
+_nfp6000_decode_basic(uint64_t addr, int *dest_island, int cpp_tgt, int mode,
+                     int addr40, int isld1, int isld0)
+{
+       int iid_lsb, idx_lsb;
+
+       switch (cpp_tgt) {
+       case NFP6000_CPPTGT_MU:
+               /* This function doesn't handle MU */
+               return NFP_ERRNO(EINVAL);
+       case NFP6000_CPPTGT_CTXPB:
+               /* This function doesn't handle CTXPB */
+               return NFP_ERRNO(EINVAL);
+       default:
+               break;
+       }
+
+       switch (mode) {
+       case 0:
+               /*
+                * For VQDR, in this mode for 32-bit addressing it would be
+                * islands 0, 16, 32 and 48 depending on channel and upper
+                * address bits. Since those are not all valid islands, most
+                * decode cases would result in bad island IDs, but we do them
+                * anyway since this is decoding an address that is already
+                * assumed to be used as-is to get to sram.
+                */
+               iid_lsb = (addr40) ? 34 : 26;
+               *dest_island = (int)(addr >> iid_lsb) & 0x3F;
+               return 0;
+       case 1:
+               /*
+                * For VQDR 32-bit, this would decode as:
+                *      Channel 0: island#0
+                *      Channel 1: island#0
+                *      Channel 2: island#1
+                *      Channel 3: island#1
+                *
+                * That would be valid as long as both islands have VQDR.
+                * Let's allow this.
+                */
+
+               idx_lsb = (addr40) ? 39 : 31;
+               if (addr & _nic_mask64(idx_lsb, idx_lsb, 0))
+                       *dest_island = isld1;
+               else
+                       *dest_island = isld0;
+
+               return 0;
+       case 2:
+               /*
+                * For VQDR 32-bit:
+                *      Channel 0: (island#0 | 0)
+                *      Channel 1: (island#0 | 1)
+                *      Channel 2: (island#1 | 0)
+                *      Channel 3: (island#1 | 1)
+                *
+                * Make sure we compare against isldN values by clearing the
+                * LSB. This is what the silicon does.
+                */
+               isld0 &= ~1;
+               isld1 &= ~1;
+
+               idx_lsb = (addr40) ? 39 : 31;
+               iid_lsb = idx_lsb - 1;
+
+               if (addr & _nic_mask64(idx_lsb, idx_lsb, 0))
+                       *dest_island = isld1 | (int)((addr >> iid_lsb) & 1);
+               else
+                       *dest_island = isld0 | (int)((addr >> iid_lsb) & 1);
+
+               return 0;
+       case 3:
+               /*
+                * In this mode the data address starts to affect the island ID
+                * so rather not allow it. In some really specific case one
+                * could use this to send the upper half of the VQDR channel to
+                * another MU, but this is getting very specific. However, as
+                * above for mode 0, this is the decoder and the caller should
+                * validate the resulting IID. This blindly does what the
+                * silicon would do.
+                */
+
+               isld0 &= ~3;
+               isld1 &= ~3;
+
+               idx_lsb = (addr40) ? 39 : 31;
+               iid_lsb = idx_lsb - 2;
+
+               if (addr & _nic_mask64(idx_lsb, idx_lsb, 0))
+                       *dest_island = isld1 | (int)((addr >> iid_lsb) & 3);
+               else
+                       *dest_island = isld0 | (int)((addr >> iid_lsb) & 3);
+
+               return 0;
+       default:
+               break;
+       }
+
+       return NFP_ERRNO(EINVAL);
+}
+
+static inline int
+_nfp6000_cppat_mu_locality_lsb(int mode, int addr40)
+{
+       switch (mode) {
+       case 0:
+       case 1:
+       case 2:
+       case 3:
+               return (addr40) ? 38 : 30;
+       default:
+               break;
+       }
+       return NFP_ERRNO(EINVAL);
+}
+
+static inline int
+_nfp6000_encode_mu(uint64_t *addr, int dest_island, int mode, int addr40,
+                  int isld1, int isld0)
+{
+       uint64_t _u64;
+       int iid_lsb, idx_lsb, locality_lsb;
+       int i, v;
+       int isld[2];
+       int da;
+
+       isld[0] = isld0;
+       isld[1] = isld1;
+       locality_lsb = _nfp6000_cppat_mu_locality_lsb(mode, addr40);
+
+       if (((*addr >> locality_lsb) & 3) == _NIC_NFP6000_MU_LOCALITY_DIRECT)
+               da = 1;
+       else
+               da = 0;
+
+       switch (mode) {
+       case 0:
+               iid_lsb = (addr40) ? 32 : 24;
+               _u64 = _nic_mask64((iid_lsb + 5), iid_lsb, 0);
+               *addr &= ~_u64;
+               *addr |= (((uint64_t)dest_island) << iid_lsb) & _u64;
+               return 0;
+       case 1:
+               if (da) {
+                       iid_lsb = (addr40) ? 32 : 24;
+                       _u64 = _nic_mask64((iid_lsb + 5), iid_lsb, 0);
+                       *addr &= ~_u64;
+                       *addr |= (((uint64_t)dest_island) << iid_lsb) & _u64;
+                       return 0;
+               }
+
+               idx_lsb = (addr40) ? 37 : 29;
+               if (dest_island == isld0) {
+                       *addr &= ~_nic_mask64(idx_lsb, idx_lsb, 0);
+                       return 0;
+               }
+
+               if (dest_island == isld1) {
+                       *addr |= (UINT64_C(1) << idx_lsb);
+                       return 0;
+               }
+
+               return NFP_ERRNO(ENODEV);
+       case 2:
+               if (da) {
+                       iid_lsb = (addr40) ? 32 : 24;
+                       _u64 = _nic_mask64((iid_lsb + 5), iid_lsb, 0);
+                       *addr &= ~_u64;
+                       *addr |= (((uint64_t)dest_island) << iid_lsb) & _u64;
+                       return 0;
+               }
+
+               /*
+                * Make sure we compare against isldN values by clearing the
+                * LSB. This is what the silicon does.
+                */
+               isld[0] &= ~1;
+               isld[1] &= ~1;
+
+               idx_lsb = (addr40) ? 37 : 29;
+               iid_lsb = idx_lsb - 1;
+
+               /*
+                * Try each option, take first one that fits. Not sure if we
+                * would want to do some smarter searching and prefer 0 or
+                * non-0 island IDs.
+                */
+
+               for (i = 0; i < 2; i++) {
+                       for (v = 0; v < 2; v++) {
+                               if (dest_island != (isld[i] | v))
+                                       continue;
+                               *addr &= ~_nic_mask64(idx_lsb, iid_lsb, 0);
+                               *addr |= (((uint64_t)i) << idx_lsb);
+                               *addr |= (((uint64_t)v) << iid_lsb);
+                               return 0;
+                       }
+               }
+               return NFP_ERRNO(ENODEV);
+       case 3:
+               /*
+                * Only the EMU will use 40 bit addressing. Silently set the
+                * direct locality bit for everyone else. The SDK toolchain
+                * uses dest_island <= 0 to test for atypical address encodings
+                * to support access to local-island CTM with a 32-but address
+                * (high-locality is effectively ignored and just used for
+                * routing to island #0).
+                */
+               if (dest_island > 0 &&
+                   (dest_island < 24 || dest_island > 26)) {
+                       *addr |= ((uint64_t)_NIC_NFP6000_MU_LOCALITY_DIRECT)
+                                << locality_lsb;
+                       da = 1;
+               }
+
+               if (da) {
+                       iid_lsb = (addr40) ? 32 : 24;
+                       _u64 = _nic_mask64((iid_lsb + 5), iid_lsb, 0);
+                       *addr &= ~_u64;
+                       *addr |= (((uint64_t)dest_island) << iid_lsb) & _u64;
+                       return 0;
+               }
+
+               isld[0] &= ~3;
+               isld[1] &= ~3;
+
+               idx_lsb = (addr40) ? 37 : 29;
+               iid_lsb = idx_lsb - 2;
+
+               for (i = 0; i < 2; i++) {
+                       for (v = 0; v < 4; v++) {
+                               if (dest_island != (isld[i] | v))
+                                       continue;
+                               *addr &= ~_nic_mask64(idx_lsb, iid_lsb, 0);
+                               *addr |= (((uint64_t)i) << idx_lsb);
+                               *addr |= (((uint64_t)v) << iid_lsb);
+                               return 0;
+                       }
+               }
+
+               return NFP_ERRNO(ENODEV);
+       default:
+               break;
+       }
+
+       return NFP_ERRNO(EINVAL);
+}
+
+static inline int
+_nfp6000_decode_mu(uint64_t addr, int *dest_island, int mode, int addr40,
+                  int isld1, int isld0)
+{
+       int iid_lsb, idx_lsb, locality_lsb;
+       int da;
+
+       locality_lsb = _nfp6000_cppat_mu_locality_lsb(mode, addr40);
+
+       if (((addr >> locality_lsb) & 3) == _NIC_NFP6000_MU_LOCALITY_DIRECT)
+               da = 1;
+       else
+               da = 0;
+
+       switch (mode) {
+       case 0:
+               iid_lsb = (addr40) ? 32 : 24;
+               *dest_island = (int)(addr >> iid_lsb) & 0x3F;
+               return 0;
+       case 1:
+               if (da) {
+                       iid_lsb = (addr40) ? 32 : 24;
+                       *dest_island = (int)(addr >> iid_lsb) & 0x3F;
+                       return 0;
+               }
+
+               idx_lsb = (addr40) ? 37 : 29;
+
+               if (addr & _nic_mask64(idx_lsb, idx_lsb, 0))
+                       *dest_island = isld1;
+               else
+                       *dest_island = isld0;
+
+               return 0;
+       case 2:
+               if (da) {
+                       iid_lsb = (addr40) ? 32 : 24;
+                       *dest_island = (int)(addr >> iid_lsb) & 0x3F;
+                       return 0;
+               }
+               /*
+                * Make sure we compare against isldN values by clearing the
+                * LSB. This is what the silicon does.
+                */
+               isld0 &= ~1;
+               isld1 &= ~1;
+
+               idx_lsb = (addr40) ? 37 : 29;
+               iid_lsb = idx_lsb - 1;
+
+               if (addr & _nic_mask64(idx_lsb, idx_lsb, 0))
+                       *dest_island = isld1 | (int)((addr >> iid_lsb) & 1);
+               else
+                       *dest_island = isld0 | (int)((addr >> iid_lsb) & 1);
+
+               return 0;
+       case 3:
+               if (da) {
+                       iid_lsb = (addr40) ? 32 : 24;
+                       *dest_island = (int)(addr >> iid_lsb) & 0x3F;
+                       return 0;
+               }
+
+               isld0 &= ~3;
+               isld1 &= ~3;
+
+               idx_lsb = (addr40) ? 37 : 29;
+               iid_lsb = idx_lsb - 2;
+
+               if (addr & _nic_mask64(idx_lsb, idx_lsb, 0))
+                       *dest_island = isld1 | (int)((addr >> iid_lsb) & 3);
+               else
+                       *dest_island = isld0 | (int)((addr >> iid_lsb) & 3);
+
+               return 0;
+       default:
+               break;
+       }
+
+       return NFP_ERRNO(EINVAL);
+}
+
+static inline int
+_nfp6000_cppat_addr_encode(uint64_t *addr, int dest_island, int cpp_tgt,
+                          int mode, int addr40, int isld1, int isld0)
+{
+       switch (cpp_tgt) {
+       case NFP6000_CPPTGT_NBI:
+       case NFP6000_CPPTGT_VQDR:
+       case NFP6000_CPPTGT_ILA:
+       case NFP6000_CPPTGT_PCIE:
+       case NFP6000_CPPTGT_ARM:
+       case NFP6000_CPPTGT_CRYPTO:
+       case NFP6000_CPPTGT_CLS:
+               return _nfp6000_encode_basic(addr, dest_island, cpp_tgt, mode,
+                                            addr40, isld1, isld0);
+
+       case NFP6000_CPPTGT_MU:
+               return _nfp6000_encode_mu(addr, dest_island, mode, addr40,
+                                         isld1, isld0);
+
+       case NFP6000_CPPTGT_CTXPB:
+               if (mode != 1 || addr40 != 0)
+                       return NFP_ERRNO(EINVAL);
+
+               *addr &= ~_nic_mask64(29, 24, 0);
+               *addr |= (((uint64_t)dest_island) << 24) &
+                         _nic_mask64(29, 24, 0);
+               return 0;
+       default:
+               break;
+       }
+
+       return NFP_ERRNO(EINVAL);
+}
+
+static inline int
+_nfp6000_cppat_addr_decode(uint64_t addr, int *dest_island, int cpp_tgt,
+                          int mode, int addr40, int isld1, int isld0)
+{
+       switch (cpp_tgt) {
+       case NFP6000_CPPTGT_NBI:
+       case NFP6000_CPPTGT_VQDR:
+       case NFP6000_CPPTGT_ILA:
+       case NFP6000_CPPTGT_PCIE:
+       case NFP6000_CPPTGT_ARM:
+       case NFP6000_CPPTGT_CRYPTO:
+       case NFP6000_CPPTGT_CLS:
+               return _nfp6000_decode_basic(addr, dest_island, cpp_tgt, mode,
+                                            addr40, isld1, isld0);
+
+       case NFP6000_CPPTGT_MU:
+               return _nfp6000_decode_mu(addr, dest_island, mode, addr40,
+                                         isld1, isld0);
+
+       case NFP6000_CPPTGT_CTXPB:
+               if (mode != 1 || addr40 != 0)
+                       return -EINVAL;
+               *dest_island = (int)(addr >> 24) & 0x3F;
+               return 0;
+       default:
+               break;
+       }
+
+       return -EINVAL;
+}
+
+static inline int
+_nfp6000_cppat_addr_iid_clear(uint64_t *addr, int cpp_tgt, int mode, int addr40)
+{
+       int iid_lsb, locality_lsb, da;
+
+       switch (cpp_tgt) {
+       case NFP6000_CPPTGT_NBI:
+       case NFP6000_CPPTGT_VQDR:
+       case NFP6000_CPPTGT_ILA:
+       case NFP6000_CPPTGT_PCIE:
+       case NFP6000_CPPTGT_ARM:
+       case NFP6000_CPPTGT_CRYPTO:
+       case NFP6000_CPPTGT_CLS:
+               switch (mode) {
+               case 0:
+                       iid_lsb = (addr40) ? 34 : 26;
+                       *addr &= ~(UINT64_C(0x3F) << iid_lsb);
+                       return 0;
+               case 1:
+                       iid_lsb = (addr40) ? 39 : 31;
+                       *addr &= ~_nic_mask64(iid_lsb, iid_lsb, 0);
+                       return 0;
+               case 2:
+                       iid_lsb = (addr40) ? 38 : 30;
+                       *addr &= ~_nic_mask64(iid_lsb + 1, iid_lsb, 0);
+                       return 0;
+               case 3:
+                       iid_lsb = (addr40) ? 37 : 29;
+                       *addr &= ~_nic_mask64(iid_lsb + 2, iid_lsb, 0);
+                       return 0;
+               default:
+                       break;
+               }
+       case NFP6000_CPPTGT_MU:
+               locality_lsb = _nfp6000_cppat_mu_locality_lsb(mode, addr40);
+               da = (((*addr >> locality_lsb) & 3) ==
+                     _NIC_NFP6000_MU_LOCALITY_DIRECT);
+               switch (mode) {
+               case 0:
+                       iid_lsb = (addr40) ? 32 : 24;
+                       *addr &= ~(UINT64_C(0x3F) << iid_lsb);
+                       return 0;
+               case 1:
+                       if (da) {
+                               iid_lsb = (addr40) ? 32 : 24;
+                               *addr &= ~(UINT64_C(0x3F) << iid_lsb);
+                               return 0;
+                       }
+                       iid_lsb = (addr40) ? 37 : 29;
+                       *addr &= ~_nic_mask64(iid_lsb, iid_lsb, 0);
+                       return 0;
+               case 2:
+                       if (da) {
+                               iid_lsb = (addr40) ? 32 : 24;
+                               *addr &= ~(UINT64_C(0x3F) << iid_lsb);
+                               return 0;
+                       }
+
+                       iid_lsb = (addr40) ? 36 : 28;
+                       *addr &= ~_nic_mask64(iid_lsb + 1, iid_lsb, 0);
+                       return 0;
+               case 3:
+                       if (da) {
+                               iid_lsb = (addr40) ? 32 : 24;
+                               *addr &= ~(UINT64_C(0x3F) << iid_lsb);
+                               return 0;
+                       }
+
+                       iid_lsb = (addr40) ? 35 : 27;
+                       *addr &= ~_nic_mask64(iid_lsb + 2, iid_lsb, 0);
+                       return 0;
+               default:
+                       break;
+               }
+       case NFP6000_CPPTGT_CTXPB:
+               if (mode != 1 || addr40 != 0)
+                       return 0;
+               *addr &= ~(UINT64_C(0x3F) << 24);
+               return 0;
+       default:
+               break;
+       }
+
+       return NFP_ERRNO(EINVAL);
+}
+
+#endif /* __NFP_CPPAT_H__ */