forked from Minki/linux
nfp: add CPP access core
Command Push Pull is the name of NFP's network on a chip. PCIe PF can access the interconnect through a number of mappings controlled via Base Access Registers. BARs allow the PF to issue pretty much any command or address any memory on the chip. Add appropriate logic and a handful of helper for simple operations like reading scalars from memories. Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
2633beb99b
commit
4cb584e0ee
@ -1,6 +1,10 @@
|
||||
obj-$(CONFIG_NFP) += nfp.o
|
||||
|
||||
nfp-objs := \
|
||||
nfpcore/nfp6000_pcie.o \
|
||||
nfpcore/nfp_cppcore.o \
|
||||
nfpcore/nfp_cpplib.o \
|
||||
nfpcore/nfp_target.o \
|
||||
nfp_main.o \
|
||||
nfp_net_common.o \
|
||||
nfp_net_ethtool.o \
|
||||
|
88
drivers/net/ethernet/netronome/nfp/nfpcore/nfp6000/nfp6000.h
Normal file
88
drivers/net/ethernet/netronome/nfp/nfpcore/nfp6000/nfp6000.h
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Netronome Systems, Inc.
|
||||
*
|
||||
* This software is dual licensed under the GNU General License Version 2,
|
||||
* June 1991 as shown in the file COPYING in the top-level directory of this
|
||||
* source tree or the BSD 2-Clause License provided below. You have the
|
||||
* option to license this software under the complete terms of either license.
|
||||
*
|
||||
* The BSD 2-Clause License:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef NFP6000_NFP6000_H
|
||||
#define NFP6000_NFP6000_H
|
||||
|
||||
#include <linux/errno.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
/* CPP Target IDs */
|
||||
#define NFP_CPP_TARGET_INVALID 0
|
||||
#define NFP_CPP_TARGET_NBI 1
|
||||
#define NFP_CPP_TARGET_QDR 2
|
||||
#define NFP_CPP_TARGET_ILA 6
|
||||
#define NFP_CPP_TARGET_MU 7
|
||||
#define NFP_CPP_TARGET_PCIE 9
|
||||
#define NFP_CPP_TARGET_ARM 10
|
||||
#define NFP_CPP_TARGET_CRYPTO 12
|
||||
#define NFP_CPP_TARGET_ISLAND_XPB 14 /* Shared with CAP */
|
||||
#define NFP_CPP_TARGET_ISLAND_CAP 14 /* Shared with XPB */
|
||||
#define NFP_CPP_TARGET_CT_XPB 14
|
||||
#define NFP_CPP_TARGET_LOCAL_SCRATCH 15
|
||||
#define NFP_CPP_TARGET_CLS NFP_CPP_TARGET_LOCAL_SCRATCH
|
||||
|
||||
#define NFP_ISL_EMEM0 24
|
||||
|
||||
#define NFP_MU_ADDR_ACCESS_TYPE_MASK 3ULL
|
||||
#define NFP_MU_ADDR_ACCESS_TYPE_DIRECT 2ULL
|
||||
|
||||
#define PUSHPULL(_pull, _push) ((_pull) << 4 | (_push) << 0)
|
||||
#define PUSH_WIDTH(_pushpull) pushpull_width((_pushpull) >> 0)
|
||||
#define PULL_WIDTH(_pushpull) pushpull_width((_pushpull) >> 4)
|
||||
|
||||
static inline int pushpull_width(int pp)
|
||||
{
|
||||
pp &= 0xf;
|
||||
|
||||
if (pp == 0)
|
||||
return -EINVAL;
|
||||
return 2 << pp;
|
||||
}
|
||||
|
||||
static inline int nfp_cppat_mu_locality_lsb(int mode, bool addr40)
|
||||
{
|
||||
switch (mode) {
|
||||
case 0 ... 3:
|
||||
return addr40 ? 38 : 30;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int nfp_target_pushpull(u32 cpp_id, u64 address);
|
||||
int nfp_target_cpp(u32 cpp_island_id, u64 cpp_island_address,
|
||||
u32 *cpp_target_id, u64 *cpp_target_address,
|
||||
const u32 *imb_table);
|
||||
|
||||
#endif /* NFP6000_NFP6000_H */
|
57
drivers/net/ethernet/netronome/nfp/nfpcore/nfp6000/nfp_xpb.h
Normal file
57
drivers/net/ethernet/netronome/nfp/nfpcore/nfp6000/nfp_xpb.h
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Netronome Systems, Inc.
|
||||
*
|
||||
* This software is dual licensed under the GNU General License Version 2,
|
||||
* June 1991 as shown in the file COPYING in the top-level directory of this
|
||||
* source tree or the BSD 2-Clause License provided below. You have the
|
||||
* option to license this software under the complete terms of either license.
|
||||
*
|
||||
* The BSD 2-Clause License:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* nfp_xpb.h
|
||||
* Author: Jason McMullan <jason.mcmullan@netronome.com>
|
||||
*/
|
||||
|
||||
#ifndef NFP6000_XPB_H
|
||||
#define NFP6000_XPB_H
|
||||
|
||||
/* For use with NFP6000 Databook "XPB Addressing" section
|
||||
*/
|
||||
#define NFP_XPB_OVERLAY(island) (((island) & 0x3f) << 24)
|
||||
|
||||
#define NFP_XPB_ISLAND(island) (NFP_XPB_OVERLAY(island) + 0x60000)
|
||||
|
||||
#define NFP_XPB_ISLAND_of(offset) (((offset) >> 24) & 0x3F)
|
||||
|
||||
/* For use with NFP6000 Databook "XPB Island and Device IDs" chapter
|
||||
*/
|
||||
#define NFP_XPB_DEVICE(island, slave, device) \
|
||||
(NFP_XPB_OVERLAY(island) | \
|
||||
(((slave) & 3) << 22) | \
|
||||
(((device) & 0x3f) << 16))
|
||||
|
||||
#endif /* NFP6000_XPB_H */
|
1364
drivers/net/ethernet/netronome/nfp/nfpcore/nfp6000_pcie.c
Normal file
1364
drivers/net/ethernet/netronome/nfp/nfpcore/nfp6000_pcie.c
Normal file
File diff suppressed because it is too large
Load Diff
46
drivers/net/ethernet/netronome/nfp/nfpcore/nfp6000_pcie.h
Normal file
46
drivers/net/ethernet/netronome/nfp/nfpcore/nfp6000_pcie.h
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Netronome Systems, Inc.
|
||||
*
|
||||
* This software is dual licensed under the GNU General License Version 2,
|
||||
* June 1991 as shown in the file COPYING in the top-level directory of this
|
||||
* source tree or the BSD 2-Clause License provided below. You have the
|
||||
* option to license this software under the complete terms of either license.
|
||||
*
|
||||
* The BSD 2-Clause License:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* nfp6000_pcie.h
|
||||
* Author: Jason McMullan <jason.mcmullan@netronome.com>
|
||||
*/
|
||||
|
||||
#ifndef NFP6000_PCIE_H
|
||||
#define NFP6000_PCIE_H
|
||||
|
||||
#include "nfp_cpp.h"
|
||||
|
||||
struct nfp_cpp *nfp_cpp_from_nfp6000_pcie(struct pci_dev *pdev);
|
||||
|
||||
#endif /* NFP6000_PCIE_H */
|
246
drivers/net/ethernet/netronome/nfp/nfpcore/nfp_arm.h
Normal file
246
drivers/net/ethernet/netronome/nfp/nfpcore/nfp_arm.h
Normal file
@ -0,0 +1,246 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Netronome Systems, Inc.
|
||||
*
|
||||
* This software is dual licensed under the GNU General License Version 2,
|
||||
* June 1991 as shown in the file COPYING in the top-level directory of this
|
||||
* source tree or the BSD 2-Clause License provided below. You have the
|
||||
* option to license this software under the complete terms of either license.
|
||||
*
|
||||
* The BSD 2-Clause License:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* nfp_arm.h
|
||||
* Definitions for ARM-based registers and memory spaces
|
||||
*/
|
||||
|
||||
#ifndef NFP_ARM_H
|
||||
#define NFP_ARM_H
|
||||
|
||||
#define NFP_ARM_QUEUE(_q) (0x100000 + (0x800 * ((_q) & 0xff)))
|
||||
#define NFP_ARM_IM 0x200000
|
||||
#define NFP_ARM_EM 0x300000
|
||||
#define NFP_ARM_GCSR 0x400000
|
||||
#define NFP_ARM_MPCORE 0x800000
|
||||
#define NFP_ARM_PL310 0xa00000
|
||||
/* Register Type: BulkBARConfig */
|
||||
#define NFP_ARM_GCSR_BULK_BAR(_bar) (0x0 + (0x4 * ((_bar) & 0x7)))
|
||||
#define NFP_ARM_GCSR_BULK_BAR_TYPE (0x1 << 31)
|
||||
#define NFP_ARM_GCSR_BULK_BAR_TYPE_BULK (0x0)
|
||||
#define NFP_ARM_GCSR_BULK_BAR_TYPE_EXPA (0x80000000)
|
||||
#define NFP_ARM_GCSR_BULK_BAR_TGT(_x) (((_x) & 0xf) << 27)
|
||||
#define NFP_ARM_GCSR_BULK_BAR_TGT_of(_x) (((_x) >> 27) & 0xf)
|
||||
#define NFP_ARM_GCSR_BULK_BAR_TOK(_x) (((_x) & 0x3) << 25)
|
||||
#define NFP_ARM_GCSR_BULK_BAR_TOK_of(_x) (((_x) >> 25) & 0x3)
|
||||
#define NFP_ARM_GCSR_BULK_BAR_LEN (0x1 << 24)
|
||||
#define NFP_ARM_GCSR_BULK_BAR_LEN_32BIT (0x0)
|
||||
#define NFP_ARM_GCSR_BULK_BAR_LEN_64BIT (0x1000000)
|
||||
#define NFP_ARM_GCSR_BULK_BAR_ADDR(_x) ((_x) & 0x7ff)
|
||||
#define NFP_ARM_GCSR_BULK_BAR_ADDR_of(_x) ((_x) & 0x7ff)
|
||||
/* Register Type: ExpansionBARConfig */
|
||||
#define NFP_ARM_GCSR_EXPA_BAR(_bar) (0x20 + (0x4 * ((_bar) & 0xf)))
|
||||
#define NFP_ARM_GCSR_EXPA_BAR_TYPE (0x1 << 31)
|
||||
#define NFP_ARM_GCSR_EXPA_BAR_TYPE_EXPA (0x0)
|
||||
#define NFP_ARM_GCSR_EXPA_BAR_TYPE_EXPL (0x80000000)
|
||||
#define NFP_ARM_GCSR_EXPA_BAR_TGT(_x) (((_x) & 0xf) << 27)
|
||||
#define NFP_ARM_GCSR_EXPA_BAR_TGT_of(_x) (((_x) >> 27) & 0xf)
|
||||
#define NFP_ARM_GCSR_EXPA_BAR_TOK(_x) (((_x) & 0x3) << 25)
|
||||
#define NFP_ARM_GCSR_EXPA_BAR_TOK_of(_x) (((_x) >> 25) & 0x3)
|
||||
#define NFP_ARM_GCSR_EXPA_BAR_LEN (0x1 << 24)
|
||||
#define NFP_ARM_GCSR_EXPA_BAR_LEN_32BIT (0x0)
|
||||
#define NFP_ARM_GCSR_EXPA_BAR_LEN_64BIT (0x1000000)
|
||||
#define NFP_ARM_GCSR_EXPA_BAR_ACT(_x) (((_x) & 0x1f) << 19)
|
||||
#define NFP_ARM_GCSR_EXPA_BAR_ACT_of(_x) (((_x) >> 19) & 0x1f)
|
||||
#define NFP_ARM_GCSR_EXPA_BAR_ACT_DERIVED (0)
|
||||
#define NFP_ARM_GCSR_EXPA_BAR_ADDR(_x) ((_x) & 0x7fff)
|
||||
#define NFP_ARM_GCSR_EXPA_BAR_ADDR_of(_x) ((_x) & 0x7fff)
|
||||
/* Register Type: ExplicitBARConfig0_Reg */
|
||||
#define NFP_ARM_GCSR_EXPL0_BAR(_bar) (0x60 + (0x4 * ((_bar) & 0x7)))
|
||||
#define NFP_ARM_GCSR_EXPL0_BAR_ADDR(_x) ((_x) & 0x3ffff)
|
||||
#define NFP_ARM_GCSR_EXPL0_BAR_ADDR_of(_x) ((_x) & 0x3ffff)
|
||||
/* Register Type: ExplicitBARConfig1_Reg */
|
||||
#define NFP_ARM_GCSR_EXPL1_BAR(_bar) (0x80 + (0x4 * ((_bar) & 0x7)))
|
||||
#define NFP_ARM_GCSR_EXPL1_BAR_POSTED (0x1 << 31)
|
||||
#define NFP_ARM_GCSR_EXPL1_BAR_SIGNAL_REF(_x) (((_x) & 0x7f) << 24)
|
||||
#define NFP_ARM_GCSR_EXPL1_BAR_SIGNAL_REF_of(_x) (((_x) >> 24) & 0x7f)
|
||||
#define NFP_ARM_GCSR_EXPL1_BAR_DATA_MASTER(_x) (((_x) & 0xff) << 16)
|
||||
#define NFP_ARM_GCSR_EXPL1_BAR_DATA_MASTER_of(_x) (((_x) >> 16) & 0xff)
|
||||
#define NFP_ARM_GCSR_EXPL1_BAR_DATA_REF(_x) ((_x) & 0x3fff)
|
||||
#define NFP_ARM_GCSR_EXPL1_BAR_DATA_REF_of(_x) ((_x) & 0x3fff)
|
||||
/* Register Type: ExplicitBARConfig2_Reg */
|
||||
#define NFP_ARM_GCSR_EXPL2_BAR(_bar) (0xa0 + (0x4 * ((_bar) & 0x7)))
|
||||
#define NFP_ARM_GCSR_EXPL2_BAR_TGT(_x) (((_x) & 0xf) << 28)
|
||||
#define NFP_ARM_GCSR_EXPL2_BAR_TGT_of(_x) (((_x) >> 28) & 0xf)
|
||||
#define NFP_ARM_GCSR_EXPL2_BAR_ACT(_x) (((_x) & 0x1f) << 23)
|
||||
#define NFP_ARM_GCSR_EXPL2_BAR_ACT_of(_x) (((_x) >> 23) & 0x1f)
|
||||
#define NFP_ARM_GCSR_EXPL2_BAR_LEN(_x) (((_x) & 0x1f) << 18)
|
||||
#define NFP_ARM_GCSR_EXPL2_BAR_LEN_of(_x) (((_x) >> 18) & 0x1f)
|
||||
#define NFP_ARM_GCSR_EXPL2_BAR_BYTE_MASK(_x) (((_x) & 0xff) << 10)
|
||||
#define NFP_ARM_GCSR_EXPL2_BAR_BYTE_MASK_of(_x) (((_x) >> 10) & 0xff)
|
||||
#define NFP_ARM_GCSR_EXPL2_BAR_TOK(_x) (((_x) & 0x3) << 8)
|
||||
#define NFP_ARM_GCSR_EXPL2_BAR_TOK_of(_x) (((_x) >> 8) & 0x3)
|
||||
#define NFP_ARM_GCSR_EXPL2_BAR_SIGNAL_MASTER(_x) ((_x) & 0xff)
|
||||
#define NFP_ARM_GCSR_EXPL2_BAR_SIGNAL_MASTER_of(_x) ((_x) & 0xff)
|
||||
/* Register Type: PostedCommandSignal */
|
||||
#define NFP_ARM_GCSR_EXPL_POST(_bar) (0xc0 + (0x4 * ((_bar) & 0x7)))
|
||||
#define NFP_ARM_GCSR_EXPL_POST_SIG_B(_x) (((_x) & 0x7f) << 25)
|
||||
#define NFP_ARM_GCSR_EXPL_POST_SIG_B_of(_x) (((_x) >> 25) & 0x7f)
|
||||
#define NFP_ARM_GCSR_EXPL_POST_SIG_B_BUS (0x1 << 24)
|
||||
#define NFP_ARM_GCSR_EXPL_POST_SIG_B_BUS_PULL (0x0)
|
||||
#define NFP_ARM_GCSR_EXPL_POST_SIG_B_BUS_PUSH (0x1000000)
|
||||
#define NFP_ARM_GCSR_EXPL_POST_SIG_A(_x) (((_x) & 0x7f) << 17)
|
||||
#define NFP_ARM_GCSR_EXPL_POST_SIG_A_of(_x) (((_x) >> 17) & 0x7f)
|
||||
#define NFP_ARM_GCSR_EXPL_POST_SIG_A_BUS (0x1 << 16)
|
||||
#define NFP_ARM_GCSR_EXPL_POST_SIG_A_BUS_PULL (0x0)
|
||||
#define NFP_ARM_GCSR_EXPL_POST_SIG_A_BUS_PUSH (0x10000)
|
||||
#define NFP_ARM_GCSR_EXPL_POST_SIG_B_RCVD (0x1 << 7)
|
||||
#define NFP_ARM_GCSR_EXPL_POST_SIG_B_VALID (0x1 << 6)
|
||||
#define NFP_ARM_GCSR_EXPL_POST_SIG_A_RCVD (0x1 << 5)
|
||||
#define NFP_ARM_GCSR_EXPL_POST_SIG_A_VALID (0x1 << 4)
|
||||
#define NFP_ARM_GCSR_EXPL_POST_CMD_COMPLETE (0x1)
|
||||
/* Register Type: MPCoreBaseAddress */
|
||||
#define NFP_ARM_GCSR_MPCORE_BASE 0x00e0
|
||||
#define NFP_ARM_GCSR_MPCORE_BASE_ADDR(_x) (((_x) & 0x7ffff) << 13)
|
||||
#define NFP_ARM_GCSR_MPCORE_BASE_ADDR_of(_x) (((_x) >> 13) & 0x7ffff)
|
||||
/* Register Type: PL310BaseAddress */
|
||||
#define NFP_ARM_GCSR_PL310_BASE 0x00e4
|
||||
#define NFP_ARM_GCSR_PL310_BASE_ADDR(_x) (((_x) & 0xfffff) << 12)
|
||||
#define NFP_ARM_GCSR_PL310_BASE_ADDR_of(_x) (((_x) >> 12) & 0xfffff)
|
||||
/* Register Type: MPCoreConfig */
|
||||
#define NFP_ARM_GCSR_MP0_CFG 0x00e8
|
||||
#define NFP_ARM_GCSR_MP0_CFG_SPI_BOOT (0x1 << 14)
|
||||
#define NFP_ARM_GCSR_MP0_CFG_ENDIAN(_x) (((_x) & 0x3) << 12)
|
||||
#define NFP_ARM_GCSR_MP0_CFG_ENDIAN_of(_x) (((_x) >> 12) & 0x3)
|
||||
#define NFP_ARM_GCSR_MP0_CFG_ENDIAN_LITTLE (0)
|
||||
#define NFP_ARM_GCSR_MP0_CFG_ENDIAN_BIG (1)
|
||||
#define NFP_ARM_GCSR_MP0_CFG_RESET_VECTOR (0x1 << 8)
|
||||
#define NFP_ARM_GCSR_MP0_CFG_RESET_VECTOR_LO (0x0)
|
||||
#define NFP_ARM_GCSR_MP0_CFG_RESET_VECTOR_HI (0x100)
|
||||
#define NFP_ARM_GCSR_MP0_CFG_OUTCLK_EN(_x) (((_x) & 0xf) << 4)
|
||||
#define NFP_ARM_GCSR_MP0_CFG_OUTCLK_EN_of(_x) (((_x) >> 4) & 0xf)
|
||||
#define NFP_ARM_GCSR_MP0_CFG_ARMID(_x) ((_x) & 0xf)
|
||||
#define NFP_ARM_GCSR_MP0_CFG_ARMID_of(_x) ((_x) & 0xf)
|
||||
/* Register Type: MPCoreIDCacheDataError */
|
||||
#define NFP_ARM_GCSR_MP0_CACHE_ERR 0x00ec
|
||||
#define NFP_ARM_GCSR_MP0_CACHE_ERR_MP0_D7 (0x1 << 15)
|
||||
#define NFP_ARM_GCSR_MP0_CACHE_ERR_MP0_D6 (0x1 << 14)
|
||||
#define NFP_ARM_GCSR_MP0_CACHE_ERR_MP0_D5 (0x1 << 13)
|
||||
#define NFP_ARM_GCSR_MP0_CACHE_ERR_MP0_D4 (0x1 << 12)
|
||||
#define NFP_ARM_GCSR_MP0_CACHE_ERR_MP0_D3 (0x1 << 11)
|
||||
#define NFP_ARM_GCSR_MP0_CACHE_ERR_MP0_D2 (0x1 << 10)
|
||||
#define NFP_ARM_GCSR_MP0_CACHE_ERR_MP0_D1 (0x1 << 9)
|
||||
#define NFP_ARM_GCSR_MP0_CACHE_ERR_MP0_D0 (0x1 << 8)
|
||||
#define NFP_ARM_GCSR_MP0_CACHE_ERR_MP0_I7 (0x1 << 7)
|
||||
#define NFP_ARM_GCSR_MP0_CACHE_ERR_MP0_I6 (0x1 << 6)
|
||||
#define NFP_ARM_GCSR_MP0_CACHE_ERR_MP0_I5 (0x1 << 5)
|
||||
#define NFP_ARM_GCSR_MP0_CACHE_ERR_MP0_I4 (0x1 << 4)
|
||||
#define NFP_ARM_GCSR_MP0_CACHE_ERR_MP0_I3 (0x1 << 3)
|
||||
#define NFP_ARM_GCSR_MP0_CACHE_ERR_MP0_I2 (0x1 << 2)
|
||||
#define NFP_ARM_GCSR_MP0_CACHE_ERR_MP0_I1 (0x1 << 1)
|
||||
#define NFP_ARM_GCSR_MP0_CACHE_ERR_MP0_I0 (0x1)
|
||||
/* Register Type: ARMDFT */
|
||||
#define NFP_ARM_GCSR_DFT 0x0100
|
||||
#define NFP_ARM_GCSR_DFT_DBG_REQ (0x1 << 20)
|
||||
#define NFP_ARM_GCSR_DFT_DBG_EN (0x1 << 19)
|
||||
#define NFP_ARM_GCSR_DFT_WFE_EVT_TRG (0x1 << 18)
|
||||
#define NFP_ARM_GCSR_DFT_ETM_WFI_RDY (0x1 << 17)
|
||||
#define NFP_ARM_GCSR_DFT_ETM_PWR_ON (0x1 << 16)
|
||||
#define NFP_ARM_GCSR_DFT_BIST_FAIL_of(_x) (((_x) >> 8) & 0xf)
|
||||
#define NFP_ARM_GCSR_DFT_BIST_DONE_of(_x) (((_x) >> 4) & 0xf)
|
||||
#define NFP_ARM_GCSR_DFT_BIST_RUN(_x) ((_x) & 0x7)
|
||||
#define NFP_ARM_GCSR_DFT_BIST_RUN_of(_x) ((_x) & 0x7)
|
||||
|
||||
/* Gasket CSRs */
|
||||
/* NOTE: These cannot be remapped, and are always at this location.
|
||||
*/
|
||||
#define NFP_ARM_GCSR_START (0xd6000000 + NFP_ARM_GCSR)
|
||||
#define NFP_ARM_GCSR_SIZE SZ_64K
|
||||
|
||||
/* BAR CSRs
|
||||
*/
|
||||
#define NFP_ARM_GCSR_BULK_BITS 11
|
||||
#define NFP_ARM_GCSR_EXPA_BITS 15
|
||||
#define NFP_ARM_GCSR_EXPL_BITS 18
|
||||
|
||||
#define NFP_ARM_GCSR_BULK_SHIFT (40 - 11)
|
||||
#define NFP_ARM_GCSR_EXPA_SHIFT (40 - 15)
|
||||
#define NFP_ARM_GCSR_EXPL_SHIFT (40 - 18)
|
||||
|
||||
#define NFP_ARM_GCSR_BULK_SIZE (1 << NFP_ARM_GCSR_BULK_SHIFT)
|
||||
#define NFP_ARM_GCSR_EXPA_SIZE (1 << NFP_ARM_GCSR_EXPA_SHIFT)
|
||||
#define NFP_ARM_GCSR_EXPL_SIZE (1 << NFP_ARM_GCSR_EXPL_SHIFT)
|
||||
|
||||
#define NFP_ARM_GCSR_EXPL2_CSR(target, action, length, \
|
||||
byte_mask, token, signal_master) \
|
||||
(NFP_ARM_GCSR_EXPL2_BAR_TGT(target) | \
|
||||
NFP_ARM_GCSR_EXPL2_BAR_ACT(action) | \
|
||||
NFP_ARM_GCSR_EXPL2_BAR_LEN(length) | \
|
||||
NFP_ARM_GCSR_EXPL2_BAR_BYTE_MASK(byte_mask) | \
|
||||
NFP_ARM_GCSR_EXPL2_BAR_TOK(token) | \
|
||||
NFP_ARM_GCSR_EXPL2_BAR_SIGNAL_MASTER(signal_master))
|
||||
#define NFP_ARM_GCSR_EXPL1_CSR(posted, signal_ref, data_master, data_ref) \
|
||||
(((posted) ? NFP_ARM_GCSR_EXPL1_BAR_POSTED : 0) | \
|
||||
NFP_ARM_GCSR_EXPL1_BAR_SIGNAL_REF(signal_ref) | \
|
||||
NFP_ARM_GCSR_EXPL1_BAR_DATA_MASTER(data_master) | \
|
||||
NFP_ARM_GCSR_EXPL1_BAR_DATA_REF(data_ref))
|
||||
#define NFP_ARM_GCSR_EXPL0_CSR(address) \
|
||||
NFP_ARM_GCSR_EXPL0_BAR_ADDR((address) >> NFP_ARM_GCSR_EXPL_SHIFT)
|
||||
#define NFP_ARM_GCSR_EXPL_POST_EXPECT_A(sig_ref, is_push, is_required) \
|
||||
(NFP_ARM_GCSR_EXPL_POST_SIG_A(sig_ref) | \
|
||||
((is_push) ? NFP_ARM_GCSR_EXPL_POST_SIG_A_BUS_PUSH : \
|
||||
NFP_ARM_GCSR_EXPL_POST_SIG_A_BUS_PULL) | \
|
||||
((is_required) ? NFP_ARM_GCSR_EXPL_POST_SIG_A_VALID : 0))
|
||||
#define NFP_ARM_GCSR_EXPL_POST_EXPECT_B(sig_ref, is_push, is_required) \
|
||||
(NFP_ARM_GCSR_EXPL_POST_SIG_B(sig_ref) | \
|
||||
((is_push) ? NFP_ARM_GCSR_EXPL_POST_SIG_B_BUS_PUSH : \
|
||||
NFP_ARM_GCSR_EXPL_POST_SIG_B_BUS_PULL) | \
|
||||
((is_required) ? NFP_ARM_GCSR_EXPL_POST_SIG_B_VALID : 0))
|
||||
|
||||
#define NFP_ARM_GCSR_EXPA_CSR(mode, target, token, is_64, action, address) \
|
||||
(((mode) ? NFP_ARM_GCSR_EXPA_BAR_TYPE_EXPL : \
|
||||
NFP_ARM_GCSR_EXPA_BAR_TYPE_EXPA) | \
|
||||
NFP_ARM_GCSR_EXPA_BAR_TGT(target) | \
|
||||
NFP_ARM_GCSR_EXPA_BAR_TOK(token) | \
|
||||
((is_64) ? NFP_ARM_GCSR_EXPA_BAR_LEN_64BIT : \
|
||||
NFP_ARM_GCSR_EXPA_BAR_LEN_32BIT) | \
|
||||
NFP_ARM_GCSR_EXPA_BAR_ACT(action) | \
|
||||
NFP_ARM_GCSR_EXPA_BAR_ADDR((address) >> NFP_ARM_GCSR_EXPA_SHIFT))
|
||||
|
||||
#define NFP_ARM_GCSR_BULK_CSR(mode, target, token, is_64, address) \
|
||||
(((mode) ? NFP_ARM_GCSR_BULK_BAR_TYPE_EXPA : \
|
||||
NFP_ARM_GCSR_BULK_BAR_TYPE_BULK) | \
|
||||
NFP_ARM_GCSR_BULK_BAR_TGT(target) | \
|
||||
NFP_ARM_GCSR_BULK_BAR_TOK(token) | \
|
||||
((is_64) ? NFP_ARM_GCSR_BULK_BAR_LEN_64BIT : \
|
||||
NFP_ARM_GCSR_BULK_BAR_LEN_32BIT) | \
|
||||
NFP_ARM_GCSR_BULK_BAR_ADDR((address) >> NFP_ARM_GCSR_BULK_SHIFT))
|
||||
|
||||
/* MP Core CSRs */
|
||||
#define NFP_ARM_MPCORE_SIZE SZ_128K
|
||||
|
||||
/* PL320 CSRs */
|
||||
#define NFP_ARM_PCSR_SIZE SZ_64K
|
||||
|
||||
#endif /* NFP_ARM_H */
|
431
drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cpp.h
Normal file
431
drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cpp.h
Normal file
@ -0,0 +1,431 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Netronome Systems, Inc.
|
||||
*
|
||||
* This software is dual licensed under the GNU General License Version 2,
|
||||
* June 1991 as shown in the file COPYING in the top-level directory of this
|
||||
* source tree or the BSD 2-Clause License provided below. You have the
|
||||
* option to license this software under the complete terms of either license.
|
||||
*
|
||||
* The BSD 2-Clause License:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* nfp_cpp.h
|
||||
* Interface for low-level NFP CPP access.
|
||||
* Authors: Jason McMullan <jason.mcmullan@netronome.com>
|
||||
* Rolf Neugebauer <rolf.neugebauer@netronome.com>
|
||||
*/
|
||||
#ifndef __NFP_CPP_H__
|
||||
#define __NFP_CPP_H__
|
||||
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#ifndef NFP_SUBSYS
|
||||
#define NFP_SUBSYS "nfp"
|
||||
#endif
|
||||
|
||||
#define nfp_err(cpp, fmt, args...) \
|
||||
dev_err(nfp_cpp_device(cpp)->parent, NFP_SUBSYS ": " fmt, ## args)
|
||||
#define nfp_warn(cpp, fmt, args...) \
|
||||
dev_warn(nfp_cpp_device(cpp)->parent, NFP_SUBSYS ": " fmt, ## args)
|
||||
#define nfp_info(cpp, fmt, args...) \
|
||||
dev_info(nfp_cpp_device(cpp)->parent, NFP_SUBSYS ": " fmt, ## args)
|
||||
#define nfp_dbg(cpp, fmt, args...) \
|
||||
dev_dbg(nfp_cpp_device(cpp)->parent, NFP_SUBSYS ": " fmt, ## args)
|
||||
|
||||
#define PCI_64BIT_BAR_COUNT 3
|
||||
|
||||
/* NFP hardware vendor/device ids.
|
||||
*/
|
||||
#define PCI_DEVICE_NFP4000 0x4000
|
||||
#define PCI_DEVICE_NFP6000 0x6000
|
||||
|
||||
#define NFP_CPP_NUM_TARGETS 16
|
||||
|
||||
struct device;
|
||||
|
||||
struct nfp_cpp_area;
|
||||
struct nfp_cpp;
|
||||
struct resource;
|
||||
|
||||
/* Wildcard indicating a CPP read or write action
|
||||
*
|
||||
* The action used will be either read or write depending on whether a
|
||||
* read or write instruction/call is performed on the NFP_CPP_ID. It
|
||||
* is recomended that the RW action is used even if all actions to be
|
||||
* performed on a NFP_CPP_ID are known to be only reads or writes.
|
||||
* Doing so will in many cases save NFP CPP internal software
|
||||
* resources.
|
||||
*/
|
||||
#define NFP_CPP_ACTION_RW 32
|
||||
|
||||
#define NFP_CPP_TARGET_ID_MASK 0x1f
|
||||
|
||||
/**
|
||||
* NFP_CPP_ID() - pack target, token, and action into a CPP ID.
|
||||
* @target: NFP CPP target id
|
||||
* @action: NFP CPP action id
|
||||
* @token: NFP CPP token id
|
||||
*
|
||||
* Create a 32-bit CPP identifier representing the access to be made.
|
||||
* These identifiers are used as parameters to other NFP CPP
|
||||
* functions. Some CPP devices may allow wildcard identifiers to be
|
||||
* specified.
|
||||
*
|
||||
* Return: NFP CPP ID
|
||||
*/
|
||||
#define NFP_CPP_ID(target, action, token) \
|
||||
((((target) & 0x7f) << 24) | (((token) & 0xff) << 16) | \
|
||||
(((action) & 0xff) << 8))
|
||||
|
||||
/**
|
||||
* NFP_CPP_ISLAND_ID() - pack target, token, action, and island into a CPP ID.
|
||||
* @target: NFP CPP target id
|
||||
* @action: NFP CPP action id
|
||||
* @token: NFP CPP token id
|
||||
* @island: NFP CPP island id
|
||||
*
|
||||
* Create a 32-bit CPP identifier representing the access to be made.
|
||||
* These identifiers are used as parameters to other NFP CPP
|
||||
* functions. Some CPP devices may allow wildcard identifiers to be
|
||||
* specified.
|
||||
*
|
||||
* Return: NFP CPP ID
|
||||
*/
|
||||
#define NFP_CPP_ISLAND_ID(target, action, token, island) \
|
||||
((((target) & 0x7f) << 24) | (((token) & 0xff) << 16) | \
|
||||
(((action) & 0xff) << 8) | (((island) & 0xff) << 0))
|
||||
|
||||
/**
|
||||
* NFP_CPP_ID_TARGET_of() - Return the NFP CPP target of a NFP CPP ID
|
||||
* @id: NFP CPP ID
|
||||
*
|
||||
* Return: NFP CPP target
|
||||
*/
|
||||
static inline u8 NFP_CPP_ID_TARGET_of(u32 id)
|
||||
{
|
||||
return (id >> 24) & NFP_CPP_TARGET_ID_MASK;
|
||||
}
|
||||
|
||||
/**
|
||||
* NFP_CPP_ID_TOKEN_of() - Return the NFP CPP token of a NFP CPP ID
|
||||
* @id: NFP CPP ID
|
||||
* Return: NFP CPP token
|
||||
*/
|
||||
static inline u8 NFP_CPP_ID_TOKEN_of(u32 id)
|
||||
{
|
||||
return (id >> 16) & 0xff;
|
||||
}
|
||||
|
||||
/**
|
||||
* NFP_CPP_ID_ACTION_of() - Return the NFP CPP action of a NFP CPP ID
|
||||
* @id: NFP CPP ID
|
||||
*
|
||||
* Return: NFP CPP action
|
||||
*/
|
||||
static inline u8 NFP_CPP_ID_ACTION_of(u32 id)
|
||||
{
|
||||
return (id >> 8) & 0xff;
|
||||
}
|
||||
|
||||
/**
|
||||
* NFP_CPP_ID_ISLAND_of() - Return the NFP CPP island of a NFP CPP ID
|
||||
* @id: NFP CPP ID
|
||||
*
|
||||
* Return: NFP CPP island
|
||||
*/
|
||||
static inline u8 NFP_CPP_ID_ISLAND_of(u32 id)
|
||||
{
|
||||
return (id >> 0) & 0xff;
|
||||
}
|
||||
|
||||
/* 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
|
||||
|
||||
/**
|
||||
* NFP_CPP_INTERFACE() - Construct a 16-bit NFP Interface ID
|
||||
* @type: NFP Interface Type
|
||||
* @unit: Unit identifier for the interface type
|
||||
* @channel: Channel identifier for the interface unit
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Return: Interface ID
|
||||
*/
|
||||
#define NFP_CPP_INTERFACE(type, unit, channel) \
|
||||
((((type) & 0xf) << 12) | \
|
||||
(((unit) & 0xf) << 8) | \
|
||||
(((channel) & 0xff) << 0))
|
||||
|
||||
/**
|
||||
* NFP_CPP_INTERFACE_TYPE_of() - Get the interface type
|
||||
* @interface: NFP Interface ID
|
||||
* Return: NFP Interface ID's type
|
||||
*/
|
||||
#define NFP_CPP_INTERFACE_TYPE_of(interface) (((interface) >> 12) & 0xf)
|
||||
|
||||
/**
|
||||
* NFP_CPP_INTERFACE_UNIT_of() - Get the interface unit
|
||||
* @interface: NFP Interface ID
|
||||
* Return: NFP Interface ID's unit
|
||||
*/
|
||||
#define NFP_CPP_INTERFACE_UNIT_of(interface) (((interface) >> 8) & 0xf)
|
||||
|
||||
/**
|
||||
* NFP_CPP_INTERFACE_CHANNEL_of() - Get the interface channel
|
||||
* @interface: NFP Interface ID
|
||||
* Return: NFP Interface ID's channel
|
||||
*/
|
||||
#define NFP_CPP_INTERFACE_CHANNEL_of(interface) (((interface) >> 0) & 0xff)
|
||||
|
||||
/* Implemented in nfp_cppcore.c */
|
||||
void nfp_cpp_free(struct nfp_cpp *cpp);
|
||||
u32 nfp_cpp_model(struct nfp_cpp *cpp);
|
||||
u16 nfp_cpp_interface(struct nfp_cpp *cpp);
|
||||
int nfp_cpp_serial(struct nfp_cpp *cpp, const u8 **serial);
|
||||
|
||||
struct nfp_cpp_area *nfp_cpp_area_alloc_with_name(struct nfp_cpp *cpp,
|
||||
u32 cpp_id,
|
||||
const char *name,
|
||||
unsigned long long address,
|
||||
unsigned long size);
|
||||
struct nfp_cpp_area *nfp_cpp_area_alloc(struct nfp_cpp *cpp, u32 cpp_id,
|
||||
unsigned long long address,
|
||||
unsigned long size);
|
||||
void nfp_cpp_area_free(struct nfp_cpp_area *area);
|
||||
int nfp_cpp_area_acquire(struct nfp_cpp_area *area);
|
||||
int nfp_cpp_area_acquire_nonblocking(struct nfp_cpp_area *area);
|
||||
void nfp_cpp_area_release(struct nfp_cpp_area *area);
|
||||
void nfp_cpp_area_release_free(struct nfp_cpp_area *area);
|
||||
int nfp_cpp_area_read(struct nfp_cpp_area *area, unsigned long offset,
|
||||
void *buffer, size_t length);
|
||||
int nfp_cpp_area_write(struct nfp_cpp_area *area, unsigned long offset,
|
||||
const void *buffer, size_t length);
|
||||
int nfp_cpp_area_check_range(struct nfp_cpp_area *area,
|
||||
unsigned long long offset, unsigned long size);
|
||||
const char *nfp_cpp_area_name(struct nfp_cpp_area *cpp_area);
|
||||
void *nfp_cpp_area_priv(struct nfp_cpp_area *cpp_area);
|
||||
struct nfp_cpp *nfp_cpp_area_cpp(struct nfp_cpp_area *cpp_area);
|
||||
struct resource *nfp_cpp_area_resource(struct nfp_cpp_area *area);
|
||||
phys_addr_t nfp_cpp_area_phys(struct nfp_cpp_area *area);
|
||||
void __iomem *nfp_cpp_area_iomem(struct nfp_cpp_area *area);
|
||||
|
||||
int nfp_cpp_area_readl(struct nfp_cpp_area *area, unsigned long offset,
|
||||
u32 *value);
|
||||
int nfp_cpp_area_writel(struct nfp_cpp_area *area, unsigned long offset,
|
||||
u32 value);
|
||||
int nfp_cpp_area_readq(struct nfp_cpp_area *area, unsigned long offset,
|
||||
u64 *value);
|
||||
int nfp_cpp_area_writeq(struct nfp_cpp_area *area, unsigned long offset,
|
||||
u64 value);
|
||||
int nfp_cpp_area_fill(struct nfp_cpp_area *area, unsigned long offset,
|
||||
u32 value, size_t length);
|
||||
|
||||
int nfp_xpb_readl(struct nfp_cpp *cpp, u32 xpb_tgt, u32 *value);
|
||||
int nfp_xpb_writel(struct nfp_cpp *cpp, u32 xpb_tgt, u32 value);
|
||||
int nfp_xpb_writelm(struct nfp_cpp *cpp, u32 xpb_tgt, u32 mask, u32 value);
|
||||
|
||||
/* Implemented in nfp_cpplib.c */
|
||||
int nfp_cpp_read(struct nfp_cpp *cpp, u32 cpp_id,
|
||||
unsigned long long address, void *kernel_vaddr, size_t length);
|
||||
int nfp_cpp_write(struct nfp_cpp *cpp, u32 cpp_id,
|
||||
unsigned long long address, const void *kernel_vaddr,
|
||||
size_t length);
|
||||
int nfp_cpp_readl(struct nfp_cpp *cpp, u32 cpp_id,
|
||||
unsigned long long address, u32 *value);
|
||||
int nfp_cpp_writel(struct nfp_cpp *cpp, u32 cpp_id,
|
||||
unsigned long long address, u32 value);
|
||||
int nfp_cpp_readq(struct nfp_cpp *cpp, u32 cpp_id,
|
||||
unsigned long long address, u64 *value);
|
||||
int nfp_cpp_writeq(struct nfp_cpp *cpp, u32 cpp_id,
|
||||
unsigned long long address, u64 value);
|
||||
|
||||
struct nfp_cpp_mutex;
|
||||
|
||||
int nfp_cpp_mutex_init(struct nfp_cpp *cpp, int target,
|
||||
unsigned long long address, u32 key_id);
|
||||
struct nfp_cpp_mutex *nfp_cpp_mutex_alloc(struct nfp_cpp *cpp, int target,
|
||||
unsigned long long address,
|
||||
u32 key_id);
|
||||
void nfp_cpp_mutex_free(struct nfp_cpp_mutex *mutex);
|
||||
int nfp_cpp_mutex_lock(struct nfp_cpp_mutex *mutex);
|
||||
int nfp_cpp_mutex_unlock(struct nfp_cpp_mutex *mutex);
|
||||
int nfp_cpp_mutex_trylock(struct nfp_cpp_mutex *mutex);
|
||||
|
||||
struct nfp_cpp_explicit;
|
||||
|
||||
struct nfp_cpp_explicit_command {
|
||||
u32 cpp_id;
|
||||
u16 data_ref;
|
||||
u8 data_master;
|
||||
u8 len;
|
||||
u8 byte_mask;
|
||||
u8 signal_master;
|
||||
u8 signal_ref;
|
||||
u8 posted;
|
||||
u8 siga;
|
||||
u8 sigb;
|
||||
s8 siga_mode;
|
||||
s8 sigb_mode;
|
||||
};
|
||||
|
||||
#define NFP_SERIAL_LEN 6
|
||||
|
||||
/**
|
||||
* struct nfp_cpp_operations - NFP CPP operations structure
|
||||
* @area_priv_size: Size of the nfp_cpp_area private data
|
||||
* @owner: Owner module
|
||||
* @init: Initialize the NFP CPP bus
|
||||
* @free: Free the bus
|
||||
* @read_serial: Read serial number to memory provided
|
||||
* @get_interface: Return CPP interface
|
||||
* @area_init: Initialize a new NFP CPP area (not serialized)
|
||||
* @area_cleanup: Clean up a NFP CPP area (not serialized)
|
||||
* @area_acquire: Acquire the NFP CPP area (serialized)
|
||||
* @area_release: Release area (serialized)
|
||||
* @area_resource: Get resource range of area (not serialized)
|
||||
* @area_phys: Get physical address of area (not serialized)
|
||||
* @area_iomem: Get iomem of area (not serialized)
|
||||
* @area_read: Perform a read from a NFP CPP area (serialized)
|
||||
* @area_write: Perform a write to a NFP CPP area (serialized)
|
||||
* @explicit_priv_size: Size of an explicit's private area
|
||||
* @explicit_acquire: Acquire an explicit area
|
||||
* @explicit_release: Release an explicit area
|
||||
* @explicit_put: Write data to send
|
||||
* @explicit_get: Read data received
|
||||
* @explicit_do: Perform the transaction
|
||||
*/
|
||||
struct nfp_cpp_operations {
|
||||
size_t area_priv_size;
|
||||
struct module *owner;
|
||||
|
||||
int (*init)(struct nfp_cpp *cpp);
|
||||
void (*free)(struct nfp_cpp *cpp);
|
||||
|
||||
void (*read_serial)(struct device *dev, u8 *serial);
|
||||
u16 (*get_interface)(struct device *dev);
|
||||
|
||||
int (*area_init)(struct nfp_cpp_area *area,
|
||||
u32 dest, unsigned long long address,
|
||||
unsigned long size);
|
||||
void (*area_cleanup)(struct nfp_cpp_area *area);
|
||||
int (*area_acquire)(struct nfp_cpp_area *area);
|
||||
void (*area_release)(struct nfp_cpp_area *area);
|
||||
struct resource *(*area_resource)(struct nfp_cpp_area *area);
|
||||
phys_addr_t (*area_phys)(struct nfp_cpp_area *area);
|
||||
void __iomem *(*area_iomem)(struct nfp_cpp_area *area);
|
||||
int (*area_read)(struct nfp_cpp_area *area, void *kernel_vaddr,
|
||||
unsigned long offset, unsigned int length);
|
||||
int (*area_write)(struct nfp_cpp_area *area, const void *kernel_vaddr,
|
||||
unsigned long offset, unsigned int length);
|
||||
|
||||
size_t explicit_priv_size;
|
||||
int (*explicit_acquire)(struct nfp_cpp_explicit *expl);
|
||||
void (*explicit_release)(struct nfp_cpp_explicit *expl);
|
||||
int (*explicit_put)(struct nfp_cpp_explicit *expl,
|
||||
const void *buff, size_t len);
|
||||
int (*explicit_get)(struct nfp_cpp_explicit *expl,
|
||||
void *buff, size_t len);
|
||||
int (*explicit_do)(struct nfp_cpp_explicit *expl,
|
||||
const struct nfp_cpp_explicit_command *cmd,
|
||||
u64 address);
|
||||
};
|
||||
|
||||
struct nfp_cpp *
|
||||
nfp_cpp_from_operations(const struct nfp_cpp_operations *ops,
|
||||
struct device *parent, void *priv);
|
||||
void *nfp_cpp_priv(struct nfp_cpp *priv);
|
||||
|
||||
int nfp_cpp_area_cache_add(struct nfp_cpp *cpp, size_t size);
|
||||
|
||||
/* The following section contains extensions to the
|
||||
* NFP CPP API, to be used in a Linux kernel-space context.
|
||||
*/
|
||||
|
||||
/* Use this channel ID for multiple virtual channel interfaces
|
||||
* (ie ARM and PCIe) when setting up the interface field.
|
||||
*/
|
||||
#define NFP_CPP_INTERFACE_CHANNEL_PEROPENER 255
|
||||
struct device *nfp_cpp_device(struct nfp_cpp *cpp);
|
||||
|
||||
/* Return code masks for nfp_cpp_explicit_do()
|
||||
*/
|
||||
#define NFP_SIGNAL_MASK_A BIT(0) /* Signal A fired */
|
||||
#define NFP_SIGNAL_MASK_B BIT(1) /* Signal B fired */
|
||||
|
||||
enum nfp_cpp_explicit_signal_mode {
|
||||
NFP_SIGNAL_NONE = 0,
|
||||
NFP_SIGNAL_PUSH = 1,
|
||||
NFP_SIGNAL_PUSH_OPTIONAL = -1,
|
||||
NFP_SIGNAL_PULL = 2,
|
||||
NFP_SIGNAL_PULL_OPTIONAL = -2,
|
||||
};
|
||||
|
||||
struct nfp_cpp_explicit *nfp_cpp_explicit_acquire(struct nfp_cpp *cpp);
|
||||
int nfp_cpp_explicit_set_target(struct nfp_cpp_explicit *expl, u32 cpp_id,
|
||||
u8 len, u8 mask);
|
||||
int nfp_cpp_explicit_set_data(struct nfp_cpp_explicit *expl,
|
||||
u8 data_master, u16 data_ref);
|
||||
int nfp_cpp_explicit_set_signal(struct nfp_cpp_explicit *expl,
|
||||
u8 signal_master, u8 signal_ref);
|
||||
int nfp_cpp_explicit_set_posted(struct nfp_cpp_explicit *expl, int posted,
|
||||
u8 siga,
|
||||
enum nfp_cpp_explicit_signal_mode siga_mode,
|
||||
u8 sigb,
|
||||
enum nfp_cpp_explicit_signal_mode sigb_mode);
|
||||
int nfp_cpp_explicit_put(struct nfp_cpp_explicit *expl,
|
||||
const void *buff, size_t len);
|
||||
int nfp_cpp_explicit_do(struct nfp_cpp_explicit *expl, u64 address);
|
||||
int nfp_cpp_explicit_get(struct nfp_cpp_explicit *expl, void *buff, size_t len);
|
||||
void nfp_cpp_explicit_release(struct nfp_cpp_explicit *expl);
|
||||
struct nfp_cpp *nfp_cpp_explicit_cpp(struct nfp_cpp_explicit *expl);
|
||||
void *nfp_cpp_explicit_priv(struct nfp_cpp_explicit *cpp_explicit);
|
||||
|
||||
/* Implemented in nfp_cpplib.c */
|
||||
|
||||
int nfp_cpp_model_autodetect(struct nfp_cpp *cpp, u32 *model);
|
||||
|
||||
int nfp_cpp_explicit_read(struct nfp_cpp *cpp, u32 cpp_id,
|
||||
u64 addr, void *buff, size_t len,
|
||||
int width_read);
|
||||
|
||||
int nfp_cpp_explicit_write(struct nfp_cpp *cpp, u32 cpp_id,
|
||||
u64 addr, const void *buff, size_t len,
|
||||
int width_write);
|
||||
|
||||
#endif /* !__NFP_CPP_H__ */
|
1706
drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cppcore.c
Normal file
1706
drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cppcore.c
Normal file
File diff suppressed because it is too large
Load Diff
281
drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cpplib.c
Normal file
281
drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cpplib.c
Normal file
@ -0,0 +1,281 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Netronome Systems, Inc.
|
||||
*
|
||||
* This software is dual licensed under the GNU General License Version 2,
|
||||
* June 1991 as shown in the file COPYING in the top-level directory of this
|
||||
* source tree or the BSD 2-Clause License provided below. You have the
|
||||
* option to license this software under the complete terms of either license.
|
||||
*
|
||||
* The BSD 2-Clause License:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* nfp_cpplib.c
|
||||
* Library of functions to access the NFP's CPP bus
|
||||
* Authors: Jakub Kicinski <jakub.kicinski@netronome.com>
|
||||
* Jason McMullan <jason.mcmullan@netronome.com>
|
||||
* Rolf Neugebauer <rolf.neugebauer@netronome.com>
|
||||
*/
|
||||
|
||||
#include <asm/unaligned.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
#include "nfp_cpp.h"
|
||||
#include "nfp6000/nfp6000.h"
|
||||
#include "nfp6000/nfp_xpb.h"
|
||||
|
||||
/* NFP6000 PL */
|
||||
#define NFP_PL_DEVICE_ID 0x00000004
|
||||
#define NFP_PL_DEVICE_ID_MASK GENMASK(7, 0)
|
||||
|
||||
#define NFP6000_ARM_GCSR_SOFTMODEL0 0x00400144
|
||||
|
||||
/**
|
||||
* nfp_cpp_readl() - Read a u32 word from a CPP location
|
||||
* @cpp: CPP device handle
|
||||
* @cpp_id: CPP ID for operation
|
||||
* @address: Address for operation
|
||||
* @value: Pointer to read buffer
|
||||
*
|
||||
* Return: length of the io, or -ERRNO
|
||||
*/
|
||||
int nfp_cpp_readl(struct nfp_cpp *cpp, u32 cpp_id,
|
||||
unsigned long long address, u32 *value)
|
||||
{
|
||||
u8 tmp[4];
|
||||
int err;
|
||||
|
||||
err = nfp_cpp_read(cpp, cpp_id, address, tmp, sizeof(tmp));
|
||||
*value = get_unaligned_le32(tmp);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* nfp_cpp_writel() - Write a u32 word to a CPP location
|
||||
* @cpp: CPP device handle
|
||||
* @cpp_id: CPP ID for operation
|
||||
* @address: Address for operation
|
||||
* @value: Value to write
|
||||
*
|
||||
* Return: length of the io, or -ERRNO
|
||||
*/
|
||||
int nfp_cpp_writel(struct nfp_cpp *cpp, u32 cpp_id,
|
||||
unsigned long long address, u32 value)
|
||||
{
|
||||
u8 tmp[4];
|
||||
|
||||
put_unaligned_le32(value, tmp);
|
||||
return nfp_cpp_write(cpp, cpp_id, address, tmp, sizeof(tmp));
|
||||
}
|
||||
|
||||
/**
|
||||
* nfp_cpp_readq() - Read a u64 word from a CPP location
|
||||
* @cpp: CPP device handle
|
||||
* @cpp_id: CPP ID for operation
|
||||
* @address: Address for operation
|
||||
* @value: Pointer to read buffer
|
||||
*
|
||||
* Return: length of the io, or -ERRNO
|
||||
*/
|
||||
int nfp_cpp_readq(struct nfp_cpp *cpp, u32 cpp_id,
|
||||
unsigned long long address, u64 *value)
|
||||
{
|
||||
u8 tmp[8];
|
||||
int err;
|
||||
|
||||
err = nfp_cpp_read(cpp, cpp_id, address, tmp, sizeof(tmp));
|
||||
*value = get_unaligned_le64(tmp);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* nfp_cpp_writeq() - Write a u64 word to a CPP location
|
||||
* @cpp: CPP device handle
|
||||
* @cpp_id: CPP ID for operation
|
||||
* @address: Address for operation
|
||||
* @value: Value to write
|
||||
*
|
||||
* Return: length of the io, or -ERRNO
|
||||
*/
|
||||
int nfp_cpp_writeq(struct nfp_cpp *cpp, u32 cpp_id,
|
||||
unsigned long long address, u64 value)
|
||||
{
|
||||
u8 tmp[8];
|
||||
|
||||
put_unaligned_le64(value, tmp);
|
||||
return nfp_cpp_write(cpp, cpp_id, address, tmp, sizeof(tmp));
|
||||
}
|
||||
|
||||
/* NOTE: This code should not use nfp_xpb_* functions,
|
||||
* as those are model-specific
|
||||
*/
|
||||
int nfp_cpp_model_autodetect(struct nfp_cpp *cpp, u32 *model)
|
||||
{
|
||||
const u32 arm_id = NFP_CPP_ID(NFP_CPP_TARGET_ARM, 0, 0);
|
||||
u32 reg;
|
||||
int err;
|
||||
|
||||
err = nfp_cpp_readl(cpp, arm_id, NFP6000_ARM_GCSR_SOFTMODEL0, model);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
/* The PL's PluDeviceID revision code is authoratative */
|
||||
*model &= ~0xff;
|
||||
err = nfp_xpb_readl(cpp, NFP_XPB_DEVICE(1, 1, 16) + NFP_PL_DEVICE_ID,
|
||||
®);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
*model |= (NFP_PL_DEVICE_ID_MASK & reg) - 0x10;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u8 nfp_bytemask(int width, u64 addr)
|
||||
{
|
||||
if (width == 8)
|
||||
return 0xff;
|
||||
else if (width == 4)
|
||||
return 0x0f << (addr & 4);
|
||||
else if (width == 2)
|
||||
return 0x03 << (addr & 6);
|
||||
else if (width == 1)
|
||||
return 0x01 << (addr & 7);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nfp_cpp_explicit_read(struct nfp_cpp *cpp, u32 cpp_id,
|
||||
u64 addr, void *buff, size_t len, int width_read)
|
||||
{
|
||||
struct nfp_cpp_explicit *expl;
|
||||
char *tmp = buff;
|
||||
int err, i, incr;
|
||||
u8 byte_mask;
|
||||
|
||||
if (len & (width_read - 1))
|
||||
return -EINVAL;
|
||||
|
||||
expl = nfp_cpp_explicit_acquire(cpp);
|
||||
if (!expl)
|
||||
return -EBUSY;
|
||||
|
||||
incr = min_t(int, 16 * width_read, 128);
|
||||
incr = min_t(int, incr, len);
|
||||
|
||||
/* Translate a NFP_CPP_ACTION_RW to action 0 */
|
||||
if (NFP_CPP_ID_ACTION_of(cpp_id) == NFP_CPP_ACTION_RW)
|
||||
cpp_id = NFP_CPP_ID(NFP_CPP_ID_TARGET_of(cpp_id), 0,
|
||||
NFP_CPP_ID_TOKEN_of(cpp_id));
|
||||
|
||||
byte_mask = nfp_bytemask(width_read, addr);
|
||||
|
||||
nfp_cpp_explicit_set_target(expl, cpp_id,
|
||||
incr / width_read - 1, byte_mask);
|
||||
nfp_cpp_explicit_set_posted(expl, 1, 0, NFP_SIGNAL_PUSH,
|
||||
0, NFP_SIGNAL_NONE);
|
||||
|
||||
for (i = 0; i < len; i += incr, addr += incr, tmp += incr) {
|
||||
if (i + incr > len) {
|
||||
incr = len - i;
|
||||
nfp_cpp_explicit_set_target(expl, cpp_id,
|
||||
incr / width_read - 1,
|
||||
0xff);
|
||||
}
|
||||
|
||||
err = nfp_cpp_explicit_do(expl, addr);
|
||||
if (err < 0)
|
||||
goto exit_release;
|
||||
|
||||
err = nfp_cpp_explicit_get(expl, tmp, incr);
|
||||
if (err < 0)
|
||||
goto exit_release;
|
||||
}
|
||||
err = len;
|
||||
exit_release:
|
||||
nfp_cpp_explicit_release(expl);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int nfp_cpp_explicit_write(struct nfp_cpp *cpp, u32 cpp_id, u64 addr,
|
||||
const void *buff, size_t len, int width_write)
|
||||
{
|
||||
struct nfp_cpp_explicit *expl;
|
||||
const char *tmp = buff;
|
||||
int err, i, incr;
|
||||
u8 byte_mask;
|
||||
|
||||
if (len & (width_write - 1))
|
||||
return -EINVAL;
|
||||
|
||||
expl = nfp_cpp_explicit_acquire(cpp);
|
||||
if (!expl)
|
||||
return -EBUSY;
|
||||
|
||||
incr = min_t(int, 16 * width_write, 128);
|
||||
incr = min_t(int, incr, len);
|
||||
|
||||
/* Translate a NFP_CPP_ACTION_RW to action 1 */
|
||||
if (NFP_CPP_ID_ACTION_of(cpp_id) == NFP_CPP_ACTION_RW)
|
||||
cpp_id = NFP_CPP_ID(NFP_CPP_ID_TARGET_of(cpp_id), 1,
|
||||
NFP_CPP_ID_TOKEN_of(cpp_id));
|
||||
|
||||
byte_mask = nfp_bytemask(width_write, addr);
|
||||
|
||||
nfp_cpp_explicit_set_target(expl, cpp_id,
|
||||
incr / width_write - 1, byte_mask);
|
||||
nfp_cpp_explicit_set_posted(expl, 1, 0, NFP_SIGNAL_PULL,
|
||||
0, NFP_SIGNAL_NONE);
|
||||
|
||||
for (i = 0; i < len; i += incr, addr += incr, tmp += incr) {
|
||||
if (i + incr > len) {
|
||||
incr = len - i;
|
||||
nfp_cpp_explicit_set_target(expl, cpp_id,
|
||||
incr / width_write - 1,
|
||||
0xff);
|
||||
}
|
||||
|
||||
err = nfp_cpp_explicit_put(expl, tmp, incr);
|
||||
if (err < 0)
|
||||
goto exit_release;
|
||||
|
||||
err = nfp_cpp_explicit_do(expl, addr);
|
||||
if (err < 0)
|
||||
goto exit_release;
|
||||
}
|
||||
err = len;
|
||||
exit_release:
|
||||
nfp_cpp_explicit_release(expl);
|
||||
|
||||
return err;
|
||||
}
|
764
drivers/net/ethernet/netronome/nfp/nfpcore/nfp_target.c
Normal file
764
drivers/net/ethernet/netronome/nfp/nfpcore/nfp_target.c
Normal file
@ -0,0 +1,764 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Netronome Systems, Inc.
|
||||
*
|
||||
* This software is dual licensed under the GNU General License Version 2,
|
||||
* June 1991 as shown in the file COPYING in the top-level directory of this
|
||||
* source tree or the BSD 2-Clause License provided below. You have the
|
||||
* option to license this software under the complete terms of either license.
|
||||
*
|
||||
* The BSD 2-Clause License:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* nfp_target.c
|
||||
* CPP Access Width Decoder
|
||||
* Authors: Jakub Kicinski <jakub.kicinski@netronome.com>
|
||||
* Jason McMullan <jason.mcmullan@netronome.com>
|
||||
* Francois H. Theron <francois.theron@netronome.com>
|
||||
*/
|
||||
|
||||
#include <linux/bitops.h>
|
||||
|
||||
#include "nfp_cpp.h"
|
||||
|
||||
#include "nfp6000/nfp6000.h"
|
||||
|
||||
#define P32 1
|
||||
#define P64 2
|
||||
|
||||
/* This structure ONLY includes items that can be done with a read or write of
|
||||
* 32-bit or 64-bit words. All others are not listed.
|
||||
*/
|
||||
|
||||
#define AT(_action, _token, _pull, _push) \
|
||||
case NFP_CPP_ID(0, (_action), (_token)): \
|
||||
return PUSHPULL((_pull), (_push))
|
||||
|
||||
static int target_rw(u32 cpp_id, int pp, int start, int len)
|
||||
{
|
||||
switch (cpp_id & NFP_CPP_ID(0, ~0, ~0)) {
|
||||
AT(0, 0, 0, pp);
|
||||
AT(1, 0, pp, 0);
|
||||
AT(NFP_CPP_ACTION_RW, 0, pp, pp);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int nfp6000_nbi_dma(u32 cpp_id)
|
||||
{
|
||||
switch (cpp_id & NFP_CPP_ID(0, ~0, ~0)) {
|
||||
AT(0, 0, 0, P64); /* ReadNbiDma */
|
||||
AT(1, 0, P64, 0); /* WriteNbiDma */
|
||||
AT(NFP_CPP_ACTION_RW, 0, P64, P64);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int nfp6000_nbi_stats(u32 cpp_id)
|
||||
{
|
||||
switch (cpp_id & NFP_CPP_ID(0, ~0, ~0)) {
|
||||
AT(0, 0, 0, P32); /* ReadNbiStats */
|
||||
AT(1, 0, P32, 0); /* WriteNbiStats */
|
||||
AT(NFP_CPP_ACTION_RW, 0, P32, P32);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int nfp6000_nbi_tm(u32 cpp_id)
|
||||
{
|
||||
switch (cpp_id & NFP_CPP_ID(0, ~0, ~0)) {
|
||||
AT(0, 0, 0, P64); /* ReadNbiTM */
|
||||
AT(1, 0, P64, 0); /* WriteNbiTM */
|
||||
AT(NFP_CPP_ACTION_RW, 0, P64, P64);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int nfp6000_nbi_ppc(u32 cpp_id)
|
||||
{
|
||||
switch (cpp_id & NFP_CPP_ID(0, ~0, ~0)) {
|
||||
AT(0, 0, 0, P64); /* ReadNbiPreclassifier */
|
||||
AT(1, 0, P64, 0); /* WriteNbiPreclassifier */
|
||||
AT(NFP_CPP_ACTION_RW, 0, P64, P64);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int nfp6000_nbi(u32 cpp_id, u64 address)
|
||||
{
|
||||
u64 rel_addr = address & 0x3fFFFF;
|
||||
|
||||
if (rel_addr < (1 << 20))
|
||||
return nfp6000_nbi_dma(cpp_id);
|
||||
if (rel_addr < (2 << 20))
|
||||
return nfp6000_nbi_stats(cpp_id);
|
||||
if (rel_addr < (3 << 20))
|
||||
return nfp6000_nbi_tm(cpp_id);
|
||||
return nfp6000_nbi_ppc(cpp_id);
|
||||
}
|
||||
|
||||
/* This structure ONLY includes items that can be done with a read or write of
|
||||
* 32-bit or 64-bit words. All others are not listed.
|
||||
*/
|
||||
static int nfp6000_mu_common(u32 cpp_id)
|
||||
{
|
||||
switch (cpp_id & NFP_CPP_ID(0, ~0, ~0)) {
|
||||
AT(NFP_CPP_ACTION_RW, 0, P64, P64); /* read_be/write_be */
|
||||
AT(NFP_CPP_ACTION_RW, 1, P64, P64); /* read_le/write_le */
|
||||
AT(NFP_CPP_ACTION_RW, 2, P64, P64); /* read_swap_be/write_swap_be */
|
||||
AT(NFP_CPP_ACTION_RW, 3, P64, P64); /* read_swap_le/write_swap_le */
|
||||
AT(0, 0, 0, P64); /* read_be */
|
||||
AT(0, 1, 0, P64); /* read_le */
|
||||
AT(0, 2, 0, P64); /* read_swap_be */
|
||||
AT(0, 3, 0, P64); /* read_swap_le */
|
||||
AT(1, 0, P64, 0); /* write_be */
|
||||
AT(1, 1, P64, 0); /* write_le */
|
||||
AT(1, 2, P64, 0); /* write_swap_be */
|
||||
AT(1, 3, P64, 0); /* write_swap_le */
|
||||
AT(3, 0, 0, P32); /* atomic_read */
|
||||
AT(3, 2, P32, 0); /* mask_compare_write */
|
||||
AT(4, 0, P32, 0); /* atomic_write */
|
||||
AT(4, 2, 0, 0); /* atomic_write_imm */
|
||||
AT(4, 3, 0, P32); /* swap_imm */
|
||||
AT(5, 0, P32, 0); /* set */
|
||||
AT(5, 3, 0, P32); /* test_set_imm */
|
||||
AT(6, 0, P32, 0); /* clr */
|
||||
AT(6, 3, 0, P32); /* test_clr_imm */
|
||||
AT(7, 0, P32, 0); /* add */
|
||||
AT(7, 3, 0, P32); /* test_add_imm */
|
||||
AT(8, 0, P32, 0); /* addsat */
|
||||
AT(8, 3, 0, P32); /* test_subsat_imm */
|
||||
AT(9, 0, P32, 0); /* sub */
|
||||
AT(9, 3, 0, P32); /* test_sub_imm */
|
||||
AT(10, 0, P32, 0); /* subsat */
|
||||
AT(10, 3, 0, P32); /* test_subsat_imm */
|
||||
AT(13, 0, 0, P32); /* microq128_get */
|
||||
AT(13, 1, 0, P32); /* microq128_pop */
|
||||
AT(13, 2, P32, 0); /* microq128_put */
|
||||
AT(15, 0, P32, 0); /* xor */
|
||||
AT(15, 3, 0, P32); /* test_xor_imm */
|
||||
AT(28, 0, 0, P32); /* read32_be */
|
||||
AT(28, 1, 0, P32); /* read32_le */
|
||||
AT(28, 2, 0, P32); /* read32_swap_be */
|
||||
AT(28, 3, 0, P32); /* read32_swap_le */
|
||||
AT(31, 0, P32, 0); /* write32_be */
|
||||
AT(31, 1, P32, 0); /* write32_le */
|
||||
AT(31, 2, P32, 0); /* write32_swap_be */
|
||||
AT(31, 3, P32, 0); /* write32_swap_le */
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int nfp6000_mu_ctm(u32 cpp_id)
|
||||
{
|
||||
switch (cpp_id & NFP_CPP_ID(0, ~0, ~0)) {
|
||||
AT(16, 1, 0, P32); /* packet_read_packet_status */
|
||||
AT(17, 1, 0, P32); /* packet_credit_get */
|
||||
AT(17, 3, 0, P64); /* packet_add_thread */
|
||||
AT(18, 2, 0, P64); /* packet_free_and_return_pointer */
|
||||
AT(18, 3, 0, P64); /* packet_return_pointer */
|
||||
AT(21, 0, 0, P64); /* pe_dma_to_memory_indirect */
|
||||
AT(21, 1, 0, P64); /* pe_dma_to_memory_indirect_swap */
|
||||
AT(21, 2, 0, P64); /* pe_dma_to_memory_indirect_free */
|
||||
AT(21, 3, 0, P64); /* pe_dma_to_memory_indirect_free_swap */
|
||||
default:
|
||||
return nfp6000_mu_common(cpp_id);
|
||||
}
|
||||
}
|
||||
|
||||
static int nfp6000_mu_emu(u32 cpp_id)
|
||||
{
|
||||
switch (cpp_id & NFP_CPP_ID(0, ~0, ~0)) {
|
||||
AT(18, 0, 0, P32); /* read_queue */
|
||||
AT(18, 1, 0, P32); /* read_queue_ring */
|
||||
AT(18, 2, P32, 0); /* write_queue */
|
||||
AT(18, 3, P32, 0); /* write_queue_ring */
|
||||
AT(20, 2, P32, 0); /* journal */
|
||||
AT(21, 0, 0, P32); /* get */
|
||||
AT(21, 1, 0, P32); /* get_eop */
|
||||
AT(21, 2, 0, P32); /* get_freely */
|
||||
AT(22, 0, 0, P32); /* pop */
|
||||
AT(22, 1, 0, P32); /* pop_eop */
|
||||
AT(22, 2, 0, P32); /* pop_freely */
|
||||
default:
|
||||
return nfp6000_mu_common(cpp_id);
|
||||
}
|
||||
}
|
||||
|
||||
static int nfp6000_mu_imu(u32 cpp_id)
|
||||
{
|
||||
return nfp6000_mu_common(cpp_id);
|
||||
}
|
||||
|
||||
static int nfp6000_mu(u32 cpp_id, u64 address)
|
||||
{
|
||||
int pp;
|
||||
|
||||
if (address < 0x2000000000ULL)
|
||||
pp = nfp6000_mu_ctm(cpp_id);
|
||||
else if (address < 0x8000000000ULL)
|
||||
pp = nfp6000_mu_emu(cpp_id);
|
||||
else if (address < 0x9800000000ULL)
|
||||
pp = nfp6000_mu_ctm(cpp_id);
|
||||
else if (address < 0x9C00000000ULL)
|
||||
pp = nfp6000_mu_emu(cpp_id);
|
||||
else if (address < 0xA000000000ULL)
|
||||
pp = nfp6000_mu_imu(cpp_id);
|
||||
else
|
||||
pp = nfp6000_mu_ctm(cpp_id);
|
||||
|
||||
return pp;
|
||||
}
|
||||
|
||||
static int nfp6000_ila(u32 cpp_id)
|
||||
{
|
||||
switch (cpp_id & NFP_CPP_ID(0, ~0, ~0)) {
|
||||
AT(0, 1, 0, P32); /* read_check_error */
|
||||
AT(2, 0, 0, P32); /* read_int */
|
||||
AT(3, 0, P32, 0); /* write_int */
|
||||
default:
|
||||
return target_rw(cpp_id, P32, 48, 4);
|
||||
}
|
||||
}
|
||||
|
||||
static int nfp6000_pci(u32 cpp_id)
|
||||
{
|
||||
switch (cpp_id & NFP_CPP_ID(0, ~0, ~0)) {
|
||||
AT(2, 0, 0, P32);
|
||||
AT(3, 0, P32, 0);
|
||||
default:
|
||||
return target_rw(cpp_id, P32, 4, 4);
|
||||
}
|
||||
}
|
||||
|
||||
static int nfp6000_crypto(u32 cpp_id)
|
||||
{
|
||||
switch (cpp_id & NFP_CPP_ID(0, ~0, ~0)) {
|
||||
AT(2, 0, P64, 0);
|
||||
default:
|
||||
return target_rw(cpp_id, P64, 12, 4);
|
||||
}
|
||||
}
|
||||
|
||||
static int nfp6000_cap_xpb(u32 cpp_id)
|
||||
{
|
||||
switch (cpp_id & NFP_CPP_ID(0, ~0, ~0)) {
|
||||
AT(0, 1, 0, P32); /* RingGet */
|
||||
AT(0, 2, P32, 0); /* Interthread Signal */
|
||||
AT(1, 1, P32, 0); /* RingPut */
|
||||
AT(1, 2, P32, 0); /* CTNNWr */
|
||||
AT(2, 0, 0, P32); /* ReflectRd, signal none */
|
||||
AT(2, 1, 0, P32); /* ReflectRd, signal self */
|
||||
AT(2, 2, 0, P32); /* ReflectRd, signal remote */
|
||||
AT(2, 3, 0, P32); /* ReflectRd, signal both */
|
||||
AT(3, 0, P32, 0); /* ReflectWr, signal none */
|
||||
AT(3, 1, P32, 0); /* ReflectWr, signal self */
|
||||
AT(3, 2, P32, 0); /* ReflectWr, signal remote */
|
||||
AT(3, 3, P32, 0); /* ReflectWr, signal both */
|
||||
AT(NFP_CPP_ACTION_RW, 1, P32, P32);
|
||||
default:
|
||||
return target_rw(cpp_id, P32, 1, 63);
|
||||
}
|
||||
}
|
||||
|
||||
static int nfp6000_cls(u32 cpp_id)
|
||||
{
|
||||
switch (cpp_id & NFP_CPP_ID(0, ~0, ~0)) {
|
||||
AT(0, 3, P32, 0); /* xor */
|
||||
AT(2, 0, P32, 0); /* set */
|
||||
AT(2, 1, P32, 0); /* clr */
|
||||
AT(4, 0, P32, 0); /* add */
|
||||
AT(4, 1, P32, 0); /* add64 */
|
||||
AT(6, 0, P32, 0); /* sub */
|
||||
AT(6, 1, P32, 0); /* sub64 */
|
||||
AT(6, 2, P32, 0); /* subsat */
|
||||
AT(8, 2, P32, 0); /* hash_mask */
|
||||
AT(8, 3, P32, 0); /* hash_clear */
|
||||
AT(9, 0, 0, P32); /* ring_get */
|
||||
AT(9, 1, 0, P32); /* ring_pop */
|
||||
AT(9, 2, 0, P32); /* ring_get_freely */
|
||||
AT(9, 3, 0, P32); /* ring_pop_freely */
|
||||
AT(10, 0, P32, 0); /* ring_put */
|
||||
AT(10, 2, P32, 0); /* ring_journal */
|
||||
AT(14, 0, P32, 0); /* reflect_write_sig_local */
|
||||
AT(15, 1, 0, P32); /* reflect_read_sig_local */
|
||||
AT(17, 2, P32, 0); /* statisic */
|
||||
AT(24, 0, 0, P32); /* ring_read */
|
||||
AT(24, 1, P32, 0); /* ring_write */
|
||||
AT(25, 0, 0, P32); /* ring_workq_add_thread */
|
||||
AT(25, 1, P32, 0); /* ring_workq_add_work */
|
||||
default:
|
||||
return target_rw(cpp_id, P32, 0, 64);
|
||||
}
|
||||
}
|
||||
|
||||
int nfp_target_pushpull(u32 cpp_id, u64 address)
|
||||
{
|
||||
switch (NFP_CPP_ID_TARGET_of(cpp_id)) {
|
||||
case NFP_CPP_TARGET_NBI:
|
||||
return nfp6000_nbi(cpp_id, address);
|
||||
case NFP_CPP_TARGET_QDR:
|
||||
return target_rw(cpp_id, P32, 24, 4);
|
||||
case NFP_CPP_TARGET_ILA:
|
||||
return nfp6000_ila(cpp_id);
|
||||
case NFP_CPP_TARGET_MU:
|
||||
return nfp6000_mu(cpp_id, address);
|
||||
case NFP_CPP_TARGET_PCIE:
|
||||
return nfp6000_pci(cpp_id);
|
||||
case NFP_CPP_TARGET_ARM:
|
||||
if (address < 0x10000)
|
||||
return target_rw(cpp_id, P64, 1, 1);
|
||||
else
|
||||
return target_rw(cpp_id, P32, 1, 1);
|
||||
case NFP_CPP_TARGET_CRYPTO:
|
||||
return nfp6000_crypto(cpp_id);
|
||||
case NFP_CPP_TARGET_CT_XPB:
|
||||
return nfp6000_cap_xpb(cpp_id);
|
||||
case NFP_CPP_TARGET_CLS:
|
||||
return nfp6000_cls(cpp_id);
|
||||
case 0:
|
||||
return target_rw(cpp_id, P32, 4, 4);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
#undef AT
|
||||
#undef P32
|
||||
#undef P64
|
||||
|
||||
/* 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 int nfp_decode_basic(u64 addr, int *dest_island, int cpp_tgt,
|
||||
int mode, bool addr40, int isld1, int isld0)
|
||||
{
|
||||
int iid_lsb, idx_lsb;
|
||||
|
||||
/* This function doesn't handle MU or CTXBP */
|
||||
if (cpp_tgt == NFP_CPP_TARGET_MU || cpp_tgt == NFP_CPP_TARGET_CT_XPB)
|
||||
return -EINVAL;
|
||||
|
||||
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 = (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 & BIT_ULL(idx_lsb))
|
||||
*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 & BIT_ULL(idx_lsb))
|
||||
*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 & BIT_ULL(idx_lsb))
|
||||
*dest_island = isld1 | (int)((addr >> iid_lsb) & 3);
|
||||
else
|
||||
*dest_island = isld0 | (int)((addr >> iid_lsb) & 3);
|
||||
|
||||
return 0;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int nfp_encode_basic_qdr(u64 addr, int dest_island, int cpp_tgt,
|
||||
int mode, bool addr40, int isld1, int isld0)
|
||||
{
|
||||
int v, ret;
|
||||
|
||||
/* Full Island ID and channel bits overlap? */
|
||||
ret = nfp_decode_basic(addr, &v, cpp_tgt, mode, addr40, isld1, isld0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* The current address won't go where expected? */
|
||||
if (dest_island != -1 && dest_island != v)
|
||||
return -EINVAL;
|
||||
|
||||
/* If dest_island was -1, we don't care where it goes. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
static int nfp_encode_basic_search(u64 *addr, int dest_island, int *isld,
|
||||
int iid_lsb, int idx_lsb, int v_max)
|
||||
{
|
||||
int i, v;
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
for (v = 0; v < v_max; v++) {
|
||||
if (dest_island != (isld[i] | v))
|
||||
continue;
|
||||
|
||||
*addr &= ~GENMASK_ULL(idx_lsb, iid_lsb);
|
||||
*addr |= ((u64)i << idx_lsb);
|
||||
*addr |= ((u64)v << iid_lsb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* 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 int nfp_encode_basic(u64 *addr, int dest_island, int cpp_tgt,
|
||||
int mode, bool addr40, int isld1, int isld0)
|
||||
{
|
||||
int iid_lsb, idx_lsb;
|
||||
int isld[2];
|
||||
u64 v64;
|
||||
|
||||
isld[0] = isld0;
|
||||
isld[1] = isld1;
|
||||
|
||||
/* This function doesn't handle MU or CTXBP */
|
||||
if (cpp_tgt == NFP_CPP_TARGET_MU || cpp_tgt == NFP_CPP_TARGET_CT_XPB)
|
||||
return -EINVAL;
|
||||
|
||||
switch (mode) {
|
||||
case 0:
|
||||
if (cpp_tgt == NFP_CPP_TARGET_QDR && !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.
|
||||
*/
|
||||
return nfp_encode_basic_qdr(*addr, cpp_tgt, dest_island,
|
||||
mode, addr40, isld1, isld0);
|
||||
|
||||
iid_lsb = addr40 ? 34 : 26;
|
||||
/* <39:34> or <31:26> */
|
||||
v64 = GENMASK_ULL(iid_lsb + 5, iid_lsb);
|
||||
*addr &= ~v64;
|
||||
*addr |= ((u64)dest_island << iid_lsb) & v64;
|
||||
return 0;
|
||||
case 1:
|
||||
if (cpp_tgt == NFP_CPP_TARGET_QDR && !addr40)
|
||||
return nfp_encode_basic_qdr(*addr, cpp_tgt, dest_island,
|
||||
mode, addr40, isld1, isld0);
|
||||
|
||||
idx_lsb = addr40 ? 39 : 31;
|
||||
if (dest_island == isld0) {
|
||||
/* Only need to clear the Index bit */
|
||||
*addr &= ~BIT_ULL(idx_lsb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dest_island == isld1) {
|
||||
/* Only need to set the Index bit */
|
||||
*addr |= BIT_ULL(idx_lsb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -ENODEV;
|
||||
case 2:
|
||||
/* iid<0> = addr<30> = channel<0>
|
||||
* channel<1> = addr<31> = Index
|
||||
*/
|
||||
if (cpp_tgt == NFP_CPP_TARGET_QDR && !addr40)
|
||||
/* 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.
|
||||
*/
|
||||
return nfp_encode_basic_qdr(*addr, cpp_tgt, dest_island,
|
||||
mode, addr40, isld1, isld0);
|
||||
|
||||
/* 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;
|
||||
|
||||
return nfp_encode_basic_search(addr, dest_island, isld,
|
||||
iid_lsb, idx_lsb, 2);
|
||||
case 3:
|
||||
if (cpp_tgt == NFP_CPP_TARGET_QDR && !addr40)
|
||||
/* iid<0> = addr<29> = data
|
||||
* iid<1> = addr<30> = channel<0>
|
||||
* channel<1> = addr<31> = Index
|
||||
*/
|
||||
return nfp_encode_basic_qdr(*addr, cpp_tgt, dest_island,
|
||||
mode, addr40, isld1, isld0);
|
||||
|
||||
isld[0] &= ~3;
|
||||
isld[1] &= ~3;
|
||||
|
||||
idx_lsb = addr40 ? 39 : 31;
|
||||
iid_lsb = idx_lsb - 2;
|
||||
|
||||
return nfp_encode_basic_search(addr, dest_island, isld,
|
||||
iid_lsb, idx_lsb, 4);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int nfp_encode_mu(u64 *addr, int dest_island, int mode,
|
||||
bool addr40, int isld1, int isld0)
|
||||
{
|
||||
int iid_lsb, idx_lsb, locality_lsb;
|
||||
int isld[2];
|
||||
u64 v64;
|
||||
int da;
|
||||
|
||||
isld[0] = isld0;
|
||||
isld[1] = isld1;
|
||||
locality_lsb = nfp_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;
|
||||
v64 = GENMASK_ULL(iid_lsb + 5, iid_lsb);
|
||||
*addr &= ~v64;
|
||||
*addr |= (((u64)dest_island) << iid_lsb) & v64;
|
||||
return 0;
|
||||
case 1:
|
||||
if (da) {
|
||||
iid_lsb = addr40 ? 32 : 24;
|
||||
v64 = GENMASK_ULL(iid_lsb + 5, iid_lsb);
|
||||
*addr &= ~v64;
|
||||
*addr |= (((u64)dest_island) << iid_lsb) & v64;
|
||||
return 0;
|
||||
}
|
||||
|
||||
idx_lsb = addr40 ? 37 : 29;
|
||||
if (dest_island == isld0) {
|
||||
*addr &= ~BIT_ULL(idx_lsb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dest_island == isld1) {
|
||||
*addr |= BIT_ULL(idx_lsb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -ENODEV;
|
||||
case 2:
|
||||
if (da) {
|
||||
iid_lsb = addr40 ? 32 : 24;
|
||||
v64 = GENMASK_ULL(iid_lsb + 5, iid_lsb);
|
||||
*addr &= ~v64;
|
||||
*addr |= (((u64)dest_island) << iid_lsb) & v64;
|
||||
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;
|
||||
|
||||
return nfp_encode_basic_search(addr, dest_island, isld,
|
||||
iid_lsb, idx_lsb, 2);
|
||||
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 effewctively ignored and just used for
|
||||
* routing to island #0).
|
||||
*/
|
||||
if (dest_island > 0 && (dest_island < 24 || dest_island > 26)) {
|
||||
*addr |= ((u64)_NIC_NFP6000_MU_LOCALITY_DIRECT)
|
||||
<< locality_lsb;
|
||||
da = 1;
|
||||
}
|
||||
|
||||
if (da) {
|
||||
iid_lsb = addr40 ? 32 : 24;
|
||||
v64 = GENMASK_ULL(iid_lsb + 5, iid_lsb);
|
||||
*addr &= ~v64;
|
||||
*addr |= (((u64)dest_island) << iid_lsb) & v64;
|
||||
return 0;
|
||||
}
|
||||
|
||||
isld[0] &= ~3;
|
||||
isld[1] &= ~3;
|
||||
|
||||
idx_lsb = addr40 ? 37 : 29;
|
||||
iid_lsb = idx_lsb - 2;
|
||||
|
||||
return nfp_encode_basic_search(addr, dest_island, isld,
|
||||
iid_lsb, idx_lsb, 4);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int nfp_cppat_addr_encode(u64 *addr, int dest_island, int cpp_tgt,
|
||||
int mode, bool addr40, int isld1, int isld0)
|
||||
{
|
||||
switch (cpp_tgt) {
|
||||
case NFP_CPP_TARGET_NBI:
|
||||
case NFP_CPP_TARGET_QDR:
|
||||
case NFP_CPP_TARGET_ILA:
|
||||
case NFP_CPP_TARGET_PCIE:
|
||||
case NFP_CPP_TARGET_ARM:
|
||||
case NFP_CPP_TARGET_CRYPTO:
|
||||
case NFP_CPP_TARGET_CLS:
|
||||
return nfp_encode_basic(addr, dest_island, cpp_tgt, mode,
|
||||
addr40, isld1, isld0);
|
||||
|
||||
case NFP_CPP_TARGET_MU:
|
||||
return nfp_encode_mu(addr, dest_island, mode,
|
||||
addr40, isld1, isld0);
|
||||
|
||||
case NFP_CPP_TARGET_CT_XPB:
|
||||
if (mode != 1 || addr40)
|
||||
return -EINVAL;
|
||||
*addr &= ~GENMASK_ULL(29, 24);
|
||||
*addr |= ((u64)dest_island << 24) & GENMASK_ULL(29, 24);
|
||||
return 0;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int nfp_target_cpp(u32 cpp_island_id, u64 cpp_island_address,
|
||||
u32 *cpp_target_id, u64 *cpp_target_address,
|
||||
const u32 *imb_table)
|
||||
{
|
||||
const int island = NFP_CPP_ID_ISLAND_of(cpp_island_id);
|
||||
const int target = NFP_CPP_ID_TARGET_of(cpp_island_id);
|
||||
u32 imb;
|
||||
int err;
|
||||
|
||||
if (target < 0 || target >= 16)
|
||||
return -EINVAL;
|
||||
|
||||
if (island == 0) {
|
||||
/* Already translated */
|
||||
*cpp_target_id = cpp_island_id;
|
||||
*cpp_target_address = cpp_island_address;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* CPP + Island only allowed on systems with IMB tables */
|
||||
if (!imb_table)
|
||||
return -EINVAL;
|
||||
|
||||
imb = imb_table[target];
|
||||
|
||||
*cpp_target_address = cpp_island_address;
|
||||
err = nfp_cppat_addr_encode(cpp_target_address, island, target,
|
||||
((imb >> 13) & 7), ((imb >> 12) & 1),
|
||||
((imb >> 6) & 0x3f), ((imb >> 0) & 0x3f));
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
*cpp_target_id = NFP_CPP_ID(target,
|
||||
NFP_CPP_ID_ACTION_of(cpp_island_id),
|
||||
NFP_CPP_ID_TOKEN_of(cpp_island_id));
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user