18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright 2017 NXP 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 58c2ecf20Sopenharmony_ci * modification, are permitted provided that the following conditions are met: 68c2ecf20Sopenharmony_ci * * Redistributions of source code must retain the above copyright 78c2ecf20Sopenharmony_ci * notice, this list of conditions and the following disclaimer. 88c2ecf20Sopenharmony_ci * * Redistributions in binary form must reproduce the above copyright 98c2ecf20Sopenharmony_ci * notice, this list of conditions and the following disclaimer in the 108c2ecf20Sopenharmony_ci * documentation and/or other materials provided with the distribution. 118c2ecf20Sopenharmony_ci * * Neither the name of NXP nor the 128c2ecf20Sopenharmony_ci * names of its contributors may be used to endorse or promote products 138c2ecf20Sopenharmony_ci * derived from this software without specific prior written permission. 148c2ecf20Sopenharmony_ci * 158c2ecf20Sopenharmony_ci * 168c2ecf20Sopenharmony_ci * ALTERNATIVELY, this software may be distributed under the terms of the 178c2ecf20Sopenharmony_ci * GNU General Public License ("GPL") as published by the Free Software 188c2ecf20Sopenharmony_ci * Foundation, either version 2 of that License or (at your option) any 198c2ecf20Sopenharmony_ci * later version. 208c2ecf20Sopenharmony_ci * 218c2ecf20Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY NXP ``AS IS'' AND ANY 228c2ecf20Sopenharmony_ci * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 238c2ecf20Sopenharmony_ci * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 248c2ecf20Sopenharmony_ci * DISCLAIMED. IN NO EVENT SHALL NXP BE LIABLE FOR ANY 258c2ecf20Sopenharmony_ci * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 268c2ecf20Sopenharmony_ci * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 278c2ecf20Sopenharmony_ci * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 288c2ecf20Sopenharmony_ci * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 298c2ecf20Sopenharmony_ci * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 308c2ecf20Sopenharmony_ci * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 318c2ecf20Sopenharmony_ci */ 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci#include <linux/slab.h> 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci#include "fman_keygen.h" 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci/* Maximum number of HW Ports */ 408c2ecf20Sopenharmony_ci#define FMAN_MAX_NUM_OF_HW_PORTS 64 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci/* Maximum number of KeyGen Schemes */ 438c2ecf20Sopenharmony_ci#define FM_KG_MAX_NUM_OF_SCHEMES 32 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci/* Number of generic KeyGen Generic Extract Command Registers */ 468c2ecf20Sopenharmony_ci#define FM_KG_NUM_OF_GENERIC_REGS 8 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci/* Dummy port ID */ 498c2ecf20Sopenharmony_ci#define DUMMY_PORT_ID 0 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci/* Select Scheme Value Register */ 528c2ecf20Sopenharmony_ci#define KG_SCH_DEF_USE_KGSE_DV_0 2 538c2ecf20Sopenharmony_ci#define KG_SCH_DEF_USE_KGSE_DV_1 3 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci/* Registers Shifting values */ 568c2ecf20Sopenharmony_ci#define FM_KG_KGAR_NUM_SHIFT 16 578c2ecf20Sopenharmony_ci#define KG_SCH_DEF_L4_PORT_SHIFT 8 588c2ecf20Sopenharmony_ci#define KG_SCH_DEF_IP_ADDR_SHIFT 18 598c2ecf20Sopenharmony_ci#define KG_SCH_HASH_CONFIG_SHIFT_SHIFT 24 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci/* KeyGen Registers bit field masks: */ 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci/* Enable bit field mask for KeyGen General Configuration Register */ 648c2ecf20Sopenharmony_ci#define FM_KG_KGGCR_EN 0x80000000 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci/* KeyGen Global Registers bit field masks */ 678c2ecf20Sopenharmony_ci#define FM_KG_KGAR_GO 0x80000000 688c2ecf20Sopenharmony_ci#define FM_KG_KGAR_READ 0x40000000 698c2ecf20Sopenharmony_ci#define FM_KG_KGAR_WRITE 0x00000000 708c2ecf20Sopenharmony_ci#define FM_KG_KGAR_SEL_SCHEME_ENTRY 0x00000000 718c2ecf20Sopenharmony_ci#define FM_KG_KGAR_SCM_WSEL_UPDATE_CNT 0x00008000 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci#define FM_KG_KGAR_ERR 0x20000000 748c2ecf20Sopenharmony_ci#define FM_KG_KGAR_SEL_CLS_PLAN_ENTRY 0x01000000 758c2ecf20Sopenharmony_ci#define FM_KG_KGAR_SEL_PORT_ENTRY 0x02000000 768c2ecf20Sopenharmony_ci#define FM_KG_KGAR_SEL_PORT_WSEL_SP 0x00008000 778c2ecf20Sopenharmony_ci#define FM_KG_KGAR_SEL_PORT_WSEL_CPP 0x00004000 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci/* Error events exceptions */ 808c2ecf20Sopenharmony_ci#define FM_EX_KG_DOUBLE_ECC 0x80000000 818c2ecf20Sopenharmony_ci#define FM_EX_KG_KEYSIZE_OVERFLOW 0x40000000 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci/* Scheme Registers bit field masks */ 848c2ecf20Sopenharmony_ci#define KG_SCH_MODE_EN 0x80000000 858c2ecf20Sopenharmony_ci#define KG_SCH_VSP_NO_KSP_EN 0x80000000 868c2ecf20Sopenharmony_ci#define KG_SCH_HASH_CONFIG_SYM 0x40000000 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci/* Known Protocol field codes */ 898c2ecf20Sopenharmony_ci#define KG_SCH_KN_PORT_ID 0x80000000 908c2ecf20Sopenharmony_ci#define KG_SCH_KN_MACDST 0x40000000 918c2ecf20Sopenharmony_ci#define KG_SCH_KN_MACSRC 0x20000000 928c2ecf20Sopenharmony_ci#define KG_SCH_KN_TCI1 0x10000000 938c2ecf20Sopenharmony_ci#define KG_SCH_KN_TCI2 0x08000000 948c2ecf20Sopenharmony_ci#define KG_SCH_KN_ETYPE 0x04000000 958c2ecf20Sopenharmony_ci#define KG_SCH_KN_PPPSID 0x02000000 968c2ecf20Sopenharmony_ci#define KG_SCH_KN_PPPID 0x01000000 978c2ecf20Sopenharmony_ci#define KG_SCH_KN_MPLS1 0x00800000 988c2ecf20Sopenharmony_ci#define KG_SCH_KN_MPLS2 0x00400000 998c2ecf20Sopenharmony_ci#define KG_SCH_KN_MPLS_LAST 0x00200000 1008c2ecf20Sopenharmony_ci#define KG_SCH_KN_IPSRC1 0x00100000 1018c2ecf20Sopenharmony_ci#define KG_SCH_KN_IPDST1 0x00080000 1028c2ecf20Sopenharmony_ci#define KG_SCH_KN_PTYPE1 0x00040000 1038c2ecf20Sopenharmony_ci#define KG_SCH_KN_IPTOS_TC1 0x00020000 1048c2ecf20Sopenharmony_ci#define KG_SCH_KN_IPV6FL1 0x00010000 1058c2ecf20Sopenharmony_ci#define KG_SCH_KN_IPSRC2 0x00008000 1068c2ecf20Sopenharmony_ci#define KG_SCH_KN_IPDST2 0x00004000 1078c2ecf20Sopenharmony_ci#define KG_SCH_KN_PTYPE2 0x00002000 1088c2ecf20Sopenharmony_ci#define KG_SCH_KN_IPTOS_TC2 0x00001000 1098c2ecf20Sopenharmony_ci#define KG_SCH_KN_IPV6FL2 0x00000800 1108c2ecf20Sopenharmony_ci#define KG_SCH_KN_GREPTYPE 0x00000400 1118c2ecf20Sopenharmony_ci#define KG_SCH_KN_IPSEC_SPI 0x00000200 1128c2ecf20Sopenharmony_ci#define KG_SCH_KN_IPSEC_NH 0x00000100 1138c2ecf20Sopenharmony_ci#define KG_SCH_KN_IPPID 0x00000080 1148c2ecf20Sopenharmony_ci#define KG_SCH_KN_L4PSRC 0x00000004 1158c2ecf20Sopenharmony_ci#define KG_SCH_KN_L4PDST 0x00000002 1168c2ecf20Sopenharmony_ci#define KG_SCH_KN_TFLG 0x00000001 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci/* NIA values */ 1198c2ecf20Sopenharmony_ci#define NIA_ENG_BMI 0x00500000 1208c2ecf20Sopenharmony_ci#define NIA_BMI_AC_ENQ_FRAME 0x00000002 1218c2ecf20Sopenharmony_ci#define ENQUEUE_KG_DFLT_NIA (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME) 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci/* Hard-coded configuration: 1248c2ecf20Sopenharmony_ci * These values are used as hard-coded values for KeyGen configuration 1258c2ecf20Sopenharmony_ci * and they replace user selections for this hard-coded version 1268c2ecf20Sopenharmony_ci */ 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci/* Hash distribution shift */ 1298c2ecf20Sopenharmony_ci#define DEFAULT_HASH_DIST_FQID_SHIFT 0 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci/* Hash shift */ 1328c2ecf20Sopenharmony_ci#define DEFAULT_HASH_SHIFT 0 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci/* Symmetric hash usage: 1358c2ecf20Sopenharmony_ci * Warning: 1368c2ecf20Sopenharmony_ci * - the value for symmetric hash usage must be in accordance with hash 1378c2ecf20Sopenharmony_ci * key defined below 1388c2ecf20Sopenharmony_ci * - according to tests performed, spreading is not working if symmetric 1398c2ecf20Sopenharmony_ci * hash is set on true 1408c2ecf20Sopenharmony_ci * So ultimately symmetric hash functionality should be always disabled: 1418c2ecf20Sopenharmony_ci */ 1428c2ecf20Sopenharmony_ci#define DEFAULT_SYMMETRIC_HASH false 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci/* Hash Key extraction fields: */ 1458c2ecf20Sopenharmony_ci#define DEFAULT_HASH_KEY_EXTRACT_FIELDS \ 1468c2ecf20Sopenharmony_ci (KG_SCH_KN_IPSRC1 | KG_SCH_KN_IPDST1 | \ 1478c2ecf20Sopenharmony_ci KG_SCH_KN_L4PSRC | KG_SCH_KN_L4PDST | \ 1488c2ecf20Sopenharmony_ci KG_SCH_KN_IPSEC_SPI) 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci/* Default values to be used as hash key in case IPv4 or L4 (TCP, UDP) 1518c2ecf20Sopenharmony_ci * don't exist in the frame 1528c2ecf20Sopenharmony_ci */ 1538c2ecf20Sopenharmony_ci/* Default IPv4 address */ 1548c2ecf20Sopenharmony_ci#define DEFAULT_HASH_KEY_IPv4_ADDR 0x0A0A0A0A 1558c2ecf20Sopenharmony_ci/* Default L4 port */ 1568c2ecf20Sopenharmony_ci#define DEFAULT_HASH_KEY_L4_PORT 0x0B0B0B0B 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci/* KeyGen Memory Mapped Registers: */ 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci/* Scheme Configuration RAM Registers */ 1618c2ecf20Sopenharmony_cistruct fman_kg_scheme_regs { 1628c2ecf20Sopenharmony_ci u32 kgse_mode; /* 0x100: MODE */ 1638c2ecf20Sopenharmony_ci u32 kgse_ekfc; /* 0x104: Extract Known Fields Command */ 1648c2ecf20Sopenharmony_ci u32 kgse_ekdv; /* 0x108: Extract Known Default Value */ 1658c2ecf20Sopenharmony_ci u32 kgse_bmch; /* 0x10C: Bit Mask Command High */ 1668c2ecf20Sopenharmony_ci u32 kgse_bmcl; /* 0x110: Bit Mask Command Low */ 1678c2ecf20Sopenharmony_ci u32 kgse_fqb; /* 0x114: Frame Queue Base */ 1688c2ecf20Sopenharmony_ci u32 kgse_hc; /* 0x118: Hash Command */ 1698c2ecf20Sopenharmony_ci u32 kgse_ppc; /* 0x11C: Policer Profile Command */ 1708c2ecf20Sopenharmony_ci u32 kgse_gec[FM_KG_NUM_OF_GENERIC_REGS]; 1718c2ecf20Sopenharmony_ci /* 0x120: Generic Extract Command */ 1728c2ecf20Sopenharmony_ci u32 kgse_spc; 1738c2ecf20Sopenharmony_ci /* 0x140: KeyGen Scheme Entry Statistic Packet Counter */ 1748c2ecf20Sopenharmony_ci u32 kgse_dv0; /* 0x144: KeyGen Scheme Entry Default Value 0 */ 1758c2ecf20Sopenharmony_ci u32 kgse_dv1; /* 0x148: KeyGen Scheme Entry Default Value 1 */ 1768c2ecf20Sopenharmony_ci u32 kgse_ccbs; 1778c2ecf20Sopenharmony_ci /* 0x14C: KeyGen Scheme Entry Coarse Classification Bit*/ 1788c2ecf20Sopenharmony_ci u32 kgse_mv; /* 0x150: KeyGen Scheme Entry Match vector */ 1798c2ecf20Sopenharmony_ci u32 kgse_om; /* 0x154: KeyGen Scheme Entry Operation Mode bits */ 1808c2ecf20Sopenharmony_ci u32 kgse_vsp; 1818c2ecf20Sopenharmony_ci /* 0x158: KeyGen Scheme Entry Virtual Storage Profile */ 1828c2ecf20Sopenharmony_ci}; 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci/* Port Partition Configuration Registers */ 1858c2ecf20Sopenharmony_cistruct fman_kg_pe_regs { 1868c2ecf20Sopenharmony_ci u32 fmkg_pe_sp; /* 0x100: KeyGen Port entry Scheme Partition */ 1878c2ecf20Sopenharmony_ci u32 fmkg_pe_cpp; 1888c2ecf20Sopenharmony_ci /* 0x104: KeyGen Port Entry Classification Plan Partition */ 1898c2ecf20Sopenharmony_ci}; 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci/* General Configuration and Status Registers 1928c2ecf20Sopenharmony_ci * Global Statistic Counters 1938c2ecf20Sopenharmony_ci * KeyGen Global Registers 1948c2ecf20Sopenharmony_ci */ 1958c2ecf20Sopenharmony_cistruct fman_kg_regs { 1968c2ecf20Sopenharmony_ci u32 fmkg_gcr; /* 0x000: KeyGen General Configuration Register */ 1978c2ecf20Sopenharmony_ci u32 res004; /* 0x004: Reserved */ 1988c2ecf20Sopenharmony_ci u32 res008; /* 0x008: Reserved */ 1998c2ecf20Sopenharmony_ci u32 fmkg_eer; /* 0x00C: KeyGen Error Event Register */ 2008c2ecf20Sopenharmony_ci u32 fmkg_eeer; /* 0x010: KeyGen Error Event Enable Register */ 2018c2ecf20Sopenharmony_ci u32 res014; /* 0x014: Reserved */ 2028c2ecf20Sopenharmony_ci u32 res018; /* 0x018: Reserved */ 2038c2ecf20Sopenharmony_ci u32 fmkg_seer; /* 0x01C: KeyGen Scheme Error Event Register */ 2048c2ecf20Sopenharmony_ci u32 fmkg_seeer; /* 0x020: KeyGen Scheme Error Event Enable Register */ 2058c2ecf20Sopenharmony_ci u32 fmkg_gsr; /* 0x024: KeyGen Global Status Register */ 2068c2ecf20Sopenharmony_ci u32 fmkg_tpc; /* 0x028: Total Packet Counter Register */ 2078c2ecf20Sopenharmony_ci u32 fmkg_serc; /* 0x02C: Soft Error Capture Register */ 2088c2ecf20Sopenharmony_ci u32 res030[4]; /* 0x030: Reserved */ 2098c2ecf20Sopenharmony_ci u32 fmkg_fdor; /* 0x034: Frame Data Offset Register */ 2108c2ecf20Sopenharmony_ci u32 fmkg_gdv0r; /* 0x038: Global Default Value Register 0 */ 2118c2ecf20Sopenharmony_ci u32 fmkg_gdv1r; /* 0x03C: Global Default Value Register 1 */ 2128c2ecf20Sopenharmony_ci u32 res04c[6]; /* 0x040: Reserved */ 2138c2ecf20Sopenharmony_ci u32 fmkg_feer; /* 0x044: Force Error Event Register */ 2148c2ecf20Sopenharmony_ci u32 res068[38]; /* 0x048: Reserved */ 2158c2ecf20Sopenharmony_ci union { 2168c2ecf20Sopenharmony_ci u32 fmkg_indirect[63]; /* 0x100: Indirect Access Registers */ 2178c2ecf20Sopenharmony_ci struct fman_kg_scheme_regs fmkg_sch; /* Scheme Registers */ 2188c2ecf20Sopenharmony_ci struct fman_kg_pe_regs fmkg_pe; /* Port Partition Registers */ 2198c2ecf20Sopenharmony_ci }; 2208c2ecf20Sopenharmony_ci u32 fmkg_ar; /* 0x1FC: KeyGen Action Register */ 2218c2ecf20Sopenharmony_ci}; 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci/* KeyGen Scheme data */ 2248c2ecf20Sopenharmony_cistruct keygen_scheme { 2258c2ecf20Sopenharmony_ci bool used; /* Specifies if this scheme is used */ 2268c2ecf20Sopenharmony_ci u8 hw_port_id; 2278c2ecf20Sopenharmony_ci /* Hardware port ID 2288c2ecf20Sopenharmony_ci * schemes sharing between multiple ports is not 2298c2ecf20Sopenharmony_ci * currently supported 2308c2ecf20Sopenharmony_ci * so we have only one port id bound to a scheme 2318c2ecf20Sopenharmony_ci */ 2328c2ecf20Sopenharmony_ci u32 base_fqid; 2338c2ecf20Sopenharmony_ci /* Base FQID: 2348c2ecf20Sopenharmony_ci * Must be between 1 and 2^24-1 2358c2ecf20Sopenharmony_ci * If hash is used and an even distribution is 2368c2ecf20Sopenharmony_ci * expected according to hash_fqid_count, 2378c2ecf20Sopenharmony_ci * base_fqid must be aligned to hash_fqid_count 2388c2ecf20Sopenharmony_ci */ 2398c2ecf20Sopenharmony_ci u32 hash_fqid_count; 2408c2ecf20Sopenharmony_ci /* FQ range for hash distribution: 2418c2ecf20Sopenharmony_ci * Must be a power of 2 2428c2ecf20Sopenharmony_ci * Represents the range of queues for spreading 2438c2ecf20Sopenharmony_ci */ 2448c2ecf20Sopenharmony_ci bool use_hashing; /* Usage of Hashing and spreading over FQ */ 2458c2ecf20Sopenharmony_ci bool symmetric_hash; /* Symmetric Hash option usage */ 2468c2ecf20Sopenharmony_ci u8 hashShift; 2478c2ecf20Sopenharmony_ci /* Hash result right shift. 2488c2ecf20Sopenharmony_ci * Select the 24 bits out of the 64 hash result. 2498c2ecf20Sopenharmony_ci * 0 means using the 24 LSB's, otherwise 2508c2ecf20Sopenharmony_ci * use the 24 LSB's after shifting right 2518c2ecf20Sopenharmony_ci */ 2528c2ecf20Sopenharmony_ci u32 match_vector; /* Match Vector */ 2538c2ecf20Sopenharmony_ci}; 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci/* KeyGen driver data */ 2568c2ecf20Sopenharmony_cistruct fman_keygen { 2578c2ecf20Sopenharmony_ci struct keygen_scheme schemes[FM_KG_MAX_NUM_OF_SCHEMES]; 2588c2ecf20Sopenharmony_ci /* Array of schemes */ 2598c2ecf20Sopenharmony_ci struct fman_kg_regs __iomem *keygen_regs; /* KeyGen registers */ 2608c2ecf20Sopenharmony_ci}; 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci/* keygen_write_ar_wait 2638c2ecf20Sopenharmony_ci * 2648c2ecf20Sopenharmony_ci * Write Action Register with specified value, wait for GO bit field to be 2658c2ecf20Sopenharmony_ci * idle and then read the error 2668c2ecf20Sopenharmony_ci * 2678c2ecf20Sopenharmony_ci * regs: KeyGen registers 2688c2ecf20Sopenharmony_ci * fmkg_ar: Action Register value 2698c2ecf20Sopenharmony_ci * 2708c2ecf20Sopenharmony_ci * Return: Zero for success or error code in case of failure 2718c2ecf20Sopenharmony_ci */ 2728c2ecf20Sopenharmony_cistatic int keygen_write_ar_wait(struct fman_kg_regs __iomem *regs, u32 fmkg_ar) 2738c2ecf20Sopenharmony_ci{ 2748c2ecf20Sopenharmony_ci iowrite32be(fmkg_ar, ®s->fmkg_ar); 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci /* Wait for GO bit field to be idle */ 2778c2ecf20Sopenharmony_ci while (fmkg_ar & FM_KG_KGAR_GO) 2788c2ecf20Sopenharmony_ci fmkg_ar = ioread32be(®s->fmkg_ar); 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci if (fmkg_ar & FM_KG_KGAR_ERR) 2818c2ecf20Sopenharmony_ci return -EINVAL; 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci return 0; 2848c2ecf20Sopenharmony_ci} 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci/* build_ar_scheme 2878c2ecf20Sopenharmony_ci * 2888c2ecf20Sopenharmony_ci * Build Action Register value for scheme settings 2898c2ecf20Sopenharmony_ci * 2908c2ecf20Sopenharmony_ci * scheme_id: Scheme ID 2918c2ecf20Sopenharmony_ci * update_counter: update scheme counter 2928c2ecf20Sopenharmony_ci * write: true for action to write the scheme or false for read action 2938c2ecf20Sopenharmony_ci * 2948c2ecf20Sopenharmony_ci * Return: AR value 2958c2ecf20Sopenharmony_ci */ 2968c2ecf20Sopenharmony_cistatic u32 build_ar_scheme(u8 scheme_id, bool update_counter, bool write) 2978c2ecf20Sopenharmony_ci{ 2988c2ecf20Sopenharmony_ci u32 rw = (u32)(write ? FM_KG_KGAR_WRITE : FM_KG_KGAR_READ); 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci return (u32)(FM_KG_KGAR_GO | 3018c2ecf20Sopenharmony_ci rw | 3028c2ecf20Sopenharmony_ci FM_KG_KGAR_SEL_SCHEME_ENTRY | 3038c2ecf20Sopenharmony_ci DUMMY_PORT_ID | 3048c2ecf20Sopenharmony_ci ((u32)scheme_id << FM_KG_KGAR_NUM_SHIFT) | 3058c2ecf20Sopenharmony_ci (update_counter ? FM_KG_KGAR_SCM_WSEL_UPDATE_CNT : 0)); 3068c2ecf20Sopenharmony_ci} 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci/* build_ar_bind_scheme 3098c2ecf20Sopenharmony_ci * 3108c2ecf20Sopenharmony_ci * Build Action Register value for port binding to schemes 3118c2ecf20Sopenharmony_ci * 3128c2ecf20Sopenharmony_ci * hwport_id: HW Port ID 3138c2ecf20Sopenharmony_ci * write: true for action to write the bind or false for read action 3148c2ecf20Sopenharmony_ci * 3158c2ecf20Sopenharmony_ci * Return: AR value 3168c2ecf20Sopenharmony_ci */ 3178c2ecf20Sopenharmony_cistatic u32 build_ar_bind_scheme(u8 hwport_id, bool write) 3188c2ecf20Sopenharmony_ci{ 3198c2ecf20Sopenharmony_ci u32 rw = write ? (u32)FM_KG_KGAR_WRITE : (u32)FM_KG_KGAR_READ; 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci return (u32)(FM_KG_KGAR_GO | 3228c2ecf20Sopenharmony_ci rw | 3238c2ecf20Sopenharmony_ci FM_KG_KGAR_SEL_PORT_ENTRY | 3248c2ecf20Sopenharmony_ci hwport_id | 3258c2ecf20Sopenharmony_ci FM_KG_KGAR_SEL_PORT_WSEL_SP); 3268c2ecf20Sopenharmony_ci} 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci/* keygen_write_sp 3298c2ecf20Sopenharmony_ci * 3308c2ecf20Sopenharmony_ci * Write Scheme Partition Register with specified value 3318c2ecf20Sopenharmony_ci * 3328c2ecf20Sopenharmony_ci * regs: KeyGen Registers 3338c2ecf20Sopenharmony_ci * sp: Scheme Partition register value 3348c2ecf20Sopenharmony_ci * add: true to add a scheme partition or false to clear 3358c2ecf20Sopenharmony_ci * 3368c2ecf20Sopenharmony_ci * Return: none 3378c2ecf20Sopenharmony_ci */ 3388c2ecf20Sopenharmony_cistatic void keygen_write_sp(struct fman_kg_regs __iomem *regs, u32 sp, bool add) 3398c2ecf20Sopenharmony_ci{ 3408c2ecf20Sopenharmony_ci u32 tmp; 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci tmp = ioread32be(®s->fmkg_pe.fmkg_pe_sp); 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci if (add) 3458c2ecf20Sopenharmony_ci tmp |= sp; 3468c2ecf20Sopenharmony_ci else 3478c2ecf20Sopenharmony_ci tmp &= ~sp; 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci iowrite32be(tmp, ®s->fmkg_pe.fmkg_pe_sp); 3508c2ecf20Sopenharmony_ci} 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci/* build_ar_bind_cls_plan 3538c2ecf20Sopenharmony_ci * 3548c2ecf20Sopenharmony_ci * Build Action Register value for Classification Plan 3558c2ecf20Sopenharmony_ci * 3568c2ecf20Sopenharmony_ci * hwport_id: HW Port ID 3578c2ecf20Sopenharmony_ci * write: true for action to write the CP or false for read action 3588c2ecf20Sopenharmony_ci * 3598c2ecf20Sopenharmony_ci * Return: AR value 3608c2ecf20Sopenharmony_ci */ 3618c2ecf20Sopenharmony_cistatic u32 build_ar_bind_cls_plan(u8 hwport_id, bool write) 3628c2ecf20Sopenharmony_ci{ 3638c2ecf20Sopenharmony_ci u32 rw = write ? (u32)FM_KG_KGAR_WRITE : (u32)FM_KG_KGAR_READ; 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci return (u32)(FM_KG_KGAR_GO | 3668c2ecf20Sopenharmony_ci rw | 3678c2ecf20Sopenharmony_ci FM_KG_KGAR_SEL_PORT_ENTRY | 3688c2ecf20Sopenharmony_ci hwport_id | 3698c2ecf20Sopenharmony_ci FM_KG_KGAR_SEL_PORT_WSEL_CPP); 3708c2ecf20Sopenharmony_ci} 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ci/* keygen_write_cpp 3738c2ecf20Sopenharmony_ci * 3748c2ecf20Sopenharmony_ci * Write Classification Plan Partition Register with specified value 3758c2ecf20Sopenharmony_ci * 3768c2ecf20Sopenharmony_ci * regs: KeyGen Registers 3778c2ecf20Sopenharmony_ci * cpp: CPP register value 3788c2ecf20Sopenharmony_ci * 3798c2ecf20Sopenharmony_ci * Return: none 3808c2ecf20Sopenharmony_ci */ 3818c2ecf20Sopenharmony_cistatic void keygen_write_cpp(struct fman_kg_regs __iomem *regs, u32 cpp) 3828c2ecf20Sopenharmony_ci{ 3838c2ecf20Sopenharmony_ci iowrite32be(cpp, ®s->fmkg_pe.fmkg_pe_cpp); 3848c2ecf20Sopenharmony_ci} 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_ci/* keygen_write_scheme 3878c2ecf20Sopenharmony_ci * 3888c2ecf20Sopenharmony_ci * Write all Schemes Registers with specified values 3898c2ecf20Sopenharmony_ci * 3908c2ecf20Sopenharmony_ci * regs: KeyGen Registers 3918c2ecf20Sopenharmony_ci * scheme_id: Scheme ID 3928c2ecf20Sopenharmony_ci * scheme_regs: Scheme registers values desired to be written 3938c2ecf20Sopenharmony_ci * update_counter: update scheme counter 3948c2ecf20Sopenharmony_ci * 3958c2ecf20Sopenharmony_ci * Return: Zero for success or error code in case of failure 3968c2ecf20Sopenharmony_ci */ 3978c2ecf20Sopenharmony_cistatic int keygen_write_scheme(struct fman_kg_regs __iomem *regs, u8 scheme_id, 3988c2ecf20Sopenharmony_ci struct fman_kg_scheme_regs *scheme_regs, 3998c2ecf20Sopenharmony_ci bool update_counter) 4008c2ecf20Sopenharmony_ci{ 4018c2ecf20Sopenharmony_ci u32 ar_reg; 4028c2ecf20Sopenharmony_ci int err, i; 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci /* Write indirect scheme registers */ 4058c2ecf20Sopenharmony_ci iowrite32be(scheme_regs->kgse_mode, ®s->fmkg_sch.kgse_mode); 4068c2ecf20Sopenharmony_ci iowrite32be(scheme_regs->kgse_ekfc, ®s->fmkg_sch.kgse_ekfc); 4078c2ecf20Sopenharmony_ci iowrite32be(scheme_regs->kgse_ekdv, ®s->fmkg_sch.kgse_ekdv); 4088c2ecf20Sopenharmony_ci iowrite32be(scheme_regs->kgse_bmch, ®s->fmkg_sch.kgse_bmch); 4098c2ecf20Sopenharmony_ci iowrite32be(scheme_regs->kgse_bmcl, ®s->fmkg_sch.kgse_bmcl); 4108c2ecf20Sopenharmony_ci iowrite32be(scheme_regs->kgse_fqb, ®s->fmkg_sch.kgse_fqb); 4118c2ecf20Sopenharmony_ci iowrite32be(scheme_regs->kgse_hc, ®s->fmkg_sch.kgse_hc); 4128c2ecf20Sopenharmony_ci iowrite32be(scheme_regs->kgse_ppc, ®s->fmkg_sch.kgse_ppc); 4138c2ecf20Sopenharmony_ci iowrite32be(scheme_regs->kgse_spc, ®s->fmkg_sch.kgse_spc); 4148c2ecf20Sopenharmony_ci iowrite32be(scheme_regs->kgse_dv0, ®s->fmkg_sch.kgse_dv0); 4158c2ecf20Sopenharmony_ci iowrite32be(scheme_regs->kgse_dv1, ®s->fmkg_sch.kgse_dv1); 4168c2ecf20Sopenharmony_ci iowrite32be(scheme_regs->kgse_ccbs, ®s->fmkg_sch.kgse_ccbs); 4178c2ecf20Sopenharmony_ci iowrite32be(scheme_regs->kgse_mv, ®s->fmkg_sch.kgse_mv); 4188c2ecf20Sopenharmony_ci iowrite32be(scheme_regs->kgse_om, ®s->fmkg_sch.kgse_om); 4198c2ecf20Sopenharmony_ci iowrite32be(scheme_regs->kgse_vsp, ®s->fmkg_sch.kgse_vsp); 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci for (i = 0 ; i < FM_KG_NUM_OF_GENERIC_REGS ; i++) 4228c2ecf20Sopenharmony_ci iowrite32be(scheme_regs->kgse_gec[i], 4238c2ecf20Sopenharmony_ci ®s->fmkg_sch.kgse_gec[i]); 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci /* Write AR (Action register) */ 4268c2ecf20Sopenharmony_ci ar_reg = build_ar_scheme(scheme_id, update_counter, true); 4278c2ecf20Sopenharmony_ci err = keygen_write_ar_wait(regs, ar_reg); 4288c2ecf20Sopenharmony_ci if (err != 0) { 4298c2ecf20Sopenharmony_ci pr_err("Writing Action Register failed\n"); 4308c2ecf20Sopenharmony_ci return err; 4318c2ecf20Sopenharmony_ci } 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ci return err; 4348c2ecf20Sopenharmony_ci} 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_ci/* get_free_scheme_id 4378c2ecf20Sopenharmony_ci * 4388c2ecf20Sopenharmony_ci * Find the first free scheme available to be used 4398c2ecf20Sopenharmony_ci * 4408c2ecf20Sopenharmony_ci * keygen: KeyGen handle 4418c2ecf20Sopenharmony_ci * scheme_id: pointer to scheme id 4428c2ecf20Sopenharmony_ci * 4438c2ecf20Sopenharmony_ci * Return: 0 on success, -EINVAL when the are no available free schemes 4448c2ecf20Sopenharmony_ci */ 4458c2ecf20Sopenharmony_cistatic int get_free_scheme_id(struct fman_keygen *keygen, u8 *scheme_id) 4468c2ecf20Sopenharmony_ci{ 4478c2ecf20Sopenharmony_ci u8 i; 4488c2ecf20Sopenharmony_ci 4498c2ecf20Sopenharmony_ci for (i = 0; i < FM_KG_MAX_NUM_OF_SCHEMES; i++) 4508c2ecf20Sopenharmony_ci if (!keygen->schemes[i].used) { 4518c2ecf20Sopenharmony_ci *scheme_id = i; 4528c2ecf20Sopenharmony_ci return 0; 4538c2ecf20Sopenharmony_ci } 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_ci return -EINVAL; 4568c2ecf20Sopenharmony_ci} 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_ci/* get_scheme 4598c2ecf20Sopenharmony_ci * 4608c2ecf20Sopenharmony_ci * Provides the scheme for specified ID 4618c2ecf20Sopenharmony_ci * 4628c2ecf20Sopenharmony_ci * keygen: KeyGen handle 4638c2ecf20Sopenharmony_ci * scheme_id: Scheme ID 4648c2ecf20Sopenharmony_ci * 4658c2ecf20Sopenharmony_ci * Return: handle to required scheme 4668c2ecf20Sopenharmony_ci */ 4678c2ecf20Sopenharmony_cistatic struct keygen_scheme *get_scheme(struct fman_keygen *keygen, 4688c2ecf20Sopenharmony_ci u8 scheme_id) 4698c2ecf20Sopenharmony_ci{ 4708c2ecf20Sopenharmony_ci if (scheme_id >= FM_KG_MAX_NUM_OF_SCHEMES) 4718c2ecf20Sopenharmony_ci return NULL; 4728c2ecf20Sopenharmony_ci return &keygen->schemes[scheme_id]; 4738c2ecf20Sopenharmony_ci} 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_ci/* keygen_bind_port_to_schemes 4768c2ecf20Sopenharmony_ci * 4778c2ecf20Sopenharmony_ci * Bind the port to schemes 4788c2ecf20Sopenharmony_ci * 4798c2ecf20Sopenharmony_ci * keygen: KeyGen handle 4808c2ecf20Sopenharmony_ci * scheme_id: id of the scheme to bind to 4818c2ecf20Sopenharmony_ci * bind: true to bind the port or false to unbind it 4828c2ecf20Sopenharmony_ci * 4838c2ecf20Sopenharmony_ci * Return: Zero for success or error code in case of failure 4848c2ecf20Sopenharmony_ci */ 4858c2ecf20Sopenharmony_cistatic int keygen_bind_port_to_schemes(struct fman_keygen *keygen, 4868c2ecf20Sopenharmony_ci u8 scheme_id, 4878c2ecf20Sopenharmony_ci bool bind) 4888c2ecf20Sopenharmony_ci{ 4898c2ecf20Sopenharmony_ci struct fman_kg_regs __iomem *keygen_regs = keygen->keygen_regs; 4908c2ecf20Sopenharmony_ci struct keygen_scheme *scheme; 4918c2ecf20Sopenharmony_ci u32 ar_reg; 4928c2ecf20Sopenharmony_ci u32 schemes_vector = 0; 4938c2ecf20Sopenharmony_ci int err; 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci scheme = get_scheme(keygen, scheme_id); 4968c2ecf20Sopenharmony_ci if (!scheme) { 4978c2ecf20Sopenharmony_ci pr_err("Requested Scheme does not exist\n"); 4988c2ecf20Sopenharmony_ci return -EINVAL; 4998c2ecf20Sopenharmony_ci } 5008c2ecf20Sopenharmony_ci if (!scheme->used) { 5018c2ecf20Sopenharmony_ci pr_err("Cannot bind port to an invalid scheme\n"); 5028c2ecf20Sopenharmony_ci return -EINVAL; 5038c2ecf20Sopenharmony_ci } 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci schemes_vector |= 1 << (31 - scheme_id); 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_ci ar_reg = build_ar_bind_scheme(scheme->hw_port_id, false); 5088c2ecf20Sopenharmony_ci err = keygen_write_ar_wait(keygen_regs, ar_reg); 5098c2ecf20Sopenharmony_ci if (err != 0) { 5108c2ecf20Sopenharmony_ci pr_err("Reading Action Register failed\n"); 5118c2ecf20Sopenharmony_ci return err; 5128c2ecf20Sopenharmony_ci } 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_ci keygen_write_sp(keygen_regs, schemes_vector, bind); 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_ci ar_reg = build_ar_bind_scheme(scheme->hw_port_id, true); 5178c2ecf20Sopenharmony_ci err = keygen_write_ar_wait(keygen_regs, ar_reg); 5188c2ecf20Sopenharmony_ci if (err != 0) { 5198c2ecf20Sopenharmony_ci pr_err("Writing Action Register failed\n"); 5208c2ecf20Sopenharmony_ci return err; 5218c2ecf20Sopenharmony_ci } 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_ci return 0; 5248c2ecf20Sopenharmony_ci} 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_ci/* keygen_scheme_setup 5278c2ecf20Sopenharmony_ci * 5288c2ecf20Sopenharmony_ci * Setup the scheme according to required configuration 5298c2ecf20Sopenharmony_ci * 5308c2ecf20Sopenharmony_ci * keygen: KeyGen handle 5318c2ecf20Sopenharmony_ci * scheme_id: scheme ID 5328c2ecf20Sopenharmony_ci * enable: true to enable scheme or false to disable it 5338c2ecf20Sopenharmony_ci * 5348c2ecf20Sopenharmony_ci * Return: Zero for success or error code in case of failure 5358c2ecf20Sopenharmony_ci */ 5368c2ecf20Sopenharmony_cistatic int keygen_scheme_setup(struct fman_keygen *keygen, u8 scheme_id, 5378c2ecf20Sopenharmony_ci bool enable) 5388c2ecf20Sopenharmony_ci{ 5398c2ecf20Sopenharmony_ci struct fman_kg_regs __iomem *keygen_regs = keygen->keygen_regs; 5408c2ecf20Sopenharmony_ci struct fman_kg_scheme_regs scheme_regs; 5418c2ecf20Sopenharmony_ci struct keygen_scheme *scheme; 5428c2ecf20Sopenharmony_ci u32 tmp_reg; 5438c2ecf20Sopenharmony_ci int err; 5448c2ecf20Sopenharmony_ci 5458c2ecf20Sopenharmony_ci scheme = get_scheme(keygen, scheme_id); 5468c2ecf20Sopenharmony_ci if (!scheme) { 5478c2ecf20Sopenharmony_ci pr_err("Requested Scheme does not exist\n"); 5488c2ecf20Sopenharmony_ci return -EINVAL; 5498c2ecf20Sopenharmony_ci } 5508c2ecf20Sopenharmony_ci if (enable && scheme->used) { 5518c2ecf20Sopenharmony_ci pr_err("The requested Scheme is already used\n"); 5528c2ecf20Sopenharmony_ci return -EINVAL; 5538c2ecf20Sopenharmony_ci } 5548c2ecf20Sopenharmony_ci 5558c2ecf20Sopenharmony_ci /* Clear scheme registers */ 5568c2ecf20Sopenharmony_ci memset(&scheme_regs, 0, sizeof(struct fman_kg_scheme_regs)); 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_ci /* Setup all scheme registers: */ 5598c2ecf20Sopenharmony_ci tmp_reg = 0; 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_ci if (enable) { 5628c2ecf20Sopenharmony_ci /* Enable Scheme */ 5638c2ecf20Sopenharmony_ci tmp_reg |= KG_SCH_MODE_EN; 5648c2ecf20Sopenharmony_ci /* Enqueue frame NIA */ 5658c2ecf20Sopenharmony_ci tmp_reg |= ENQUEUE_KG_DFLT_NIA; 5668c2ecf20Sopenharmony_ci } 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_ci scheme_regs.kgse_mode = tmp_reg; 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_ci scheme_regs.kgse_mv = scheme->match_vector; 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_ci /* Scheme don't override StorageProfile: 5738c2ecf20Sopenharmony_ci * valid only for DPAA_VERSION >= 11 5748c2ecf20Sopenharmony_ci */ 5758c2ecf20Sopenharmony_ci scheme_regs.kgse_vsp = KG_SCH_VSP_NO_KSP_EN; 5768c2ecf20Sopenharmony_ci 5778c2ecf20Sopenharmony_ci /* Configure Hard-Coded Rx Hashing: */ 5788c2ecf20Sopenharmony_ci 5798c2ecf20Sopenharmony_ci if (scheme->use_hashing) { 5808c2ecf20Sopenharmony_ci /* configure kgse_ekfc */ 5818c2ecf20Sopenharmony_ci scheme_regs.kgse_ekfc = DEFAULT_HASH_KEY_EXTRACT_FIELDS; 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_ci /* configure kgse_ekdv */ 5848c2ecf20Sopenharmony_ci tmp_reg = 0; 5858c2ecf20Sopenharmony_ci tmp_reg |= (KG_SCH_DEF_USE_KGSE_DV_0 << 5868c2ecf20Sopenharmony_ci KG_SCH_DEF_IP_ADDR_SHIFT); 5878c2ecf20Sopenharmony_ci tmp_reg |= (KG_SCH_DEF_USE_KGSE_DV_1 << 5888c2ecf20Sopenharmony_ci KG_SCH_DEF_L4_PORT_SHIFT); 5898c2ecf20Sopenharmony_ci scheme_regs.kgse_ekdv = tmp_reg; 5908c2ecf20Sopenharmony_ci 5918c2ecf20Sopenharmony_ci /* configure kgse_dv0 */ 5928c2ecf20Sopenharmony_ci scheme_regs.kgse_dv0 = DEFAULT_HASH_KEY_IPv4_ADDR; 5938c2ecf20Sopenharmony_ci /* configure kgse_dv1 */ 5948c2ecf20Sopenharmony_ci scheme_regs.kgse_dv1 = DEFAULT_HASH_KEY_L4_PORT; 5958c2ecf20Sopenharmony_ci 5968c2ecf20Sopenharmony_ci /* configure kgse_hc */ 5978c2ecf20Sopenharmony_ci tmp_reg = 0; 5988c2ecf20Sopenharmony_ci tmp_reg |= ((scheme->hash_fqid_count - 1) << 5998c2ecf20Sopenharmony_ci DEFAULT_HASH_DIST_FQID_SHIFT); 6008c2ecf20Sopenharmony_ci tmp_reg |= scheme->hashShift << KG_SCH_HASH_CONFIG_SHIFT_SHIFT; 6018c2ecf20Sopenharmony_ci 6028c2ecf20Sopenharmony_ci if (scheme->symmetric_hash) { 6038c2ecf20Sopenharmony_ci /* Normally extraction key should be verified if 6048c2ecf20Sopenharmony_ci * complies with symmetric hash 6058c2ecf20Sopenharmony_ci * But because extraction is hard-coded, we are sure 6068c2ecf20Sopenharmony_ci * the key is symmetric 6078c2ecf20Sopenharmony_ci */ 6088c2ecf20Sopenharmony_ci tmp_reg |= KG_SCH_HASH_CONFIG_SYM; 6098c2ecf20Sopenharmony_ci } 6108c2ecf20Sopenharmony_ci scheme_regs.kgse_hc = tmp_reg; 6118c2ecf20Sopenharmony_ci } else { 6128c2ecf20Sopenharmony_ci scheme_regs.kgse_ekfc = 0; 6138c2ecf20Sopenharmony_ci scheme_regs.kgse_hc = 0; 6148c2ecf20Sopenharmony_ci scheme_regs.kgse_ekdv = 0; 6158c2ecf20Sopenharmony_ci scheme_regs.kgse_dv0 = 0; 6168c2ecf20Sopenharmony_ci scheme_regs.kgse_dv1 = 0; 6178c2ecf20Sopenharmony_ci } 6188c2ecf20Sopenharmony_ci 6198c2ecf20Sopenharmony_ci /* configure kgse_fqb: Scheme FQID base */ 6208c2ecf20Sopenharmony_ci tmp_reg = 0; 6218c2ecf20Sopenharmony_ci tmp_reg |= scheme->base_fqid; 6228c2ecf20Sopenharmony_ci scheme_regs.kgse_fqb = tmp_reg; 6238c2ecf20Sopenharmony_ci 6248c2ecf20Sopenharmony_ci /* features not used by hard-coded configuration */ 6258c2ecf20Sopenharmony_ci scheme_regs.kgse_bmch = 0; 6268c2ecf20Sopenharmony_ci scheme_regs.kgse_bmcl = 0; 6278c2ecf20Sopenharmony_ci scheme_regs.kgse_spc = 0; 6288c2ecf20Sopenharmony_ci 6298c2ecf20Sopenharmony_ci /* Write scheme registers */ 6308c2ecf20Sopenharmony_ci err = keygen_write_scheme(keygen_regs, scheme_id, &scheme_regs, true); 6318c2ecf20Sopenharmony_ci if (err != 0) { 6328c2ecf20Sopenharmony_ci pr_err("Writing scheme registers failed\n"); 6338c2ecf20Sopenharmony_ci return err; 6348c2ecf20Sopenharmony_ci } 6358c2ecf20Sopenharmony_ci 6368c2ecf20Sopenharmony_ci /* Update used field for Scheme */ 6378c2ecf20Sopenharmony_ci scheme->used = enable; 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_ci return 0; 6408c2ecf20Sopenharmony_ci} 6418c2ecf20Sopenharmony_ci 6428c2ecf20Sopenharmony_ci/* keygen_init 6438c2ecf20Sopenharmony_ci * 6448c2ecf20Sopenharmony_ci * KeyGen initialization: 6458c2ecf20Sopenharmony_ci * Initializes and enables KeyGen, allocate driver memory, setup registers, 6468c2ecf20Sopenharmony_ci * clear port bindings, invalidate all schemes 6478c2ecf20Sopenharmony_ci * 6488c2ecf20Sopenharmony_ci * keygen_regs: KeyGen registers base address 6498c2ecf20Sopenharmony_ci * 6508c2ecf20Sopenharmony_ci * Return: Handle to KeyGen driver 6518c2ecf20Sopenharmony_ci */ 6528c2ecf20Sopenharmony_cistruct fman_keygen *keygen_init(struct fman_kg_regs __iomem *keygen_regs) 6538c2ecf20Sopenharmony_ci{ 6548c2ecf20Sopenharmony_ci struct fman_keygen *keygen; 6558c2ecf20Sopenharmony_ci u32 ar; 6568c2ecf20Sopenharmony_ci int i; 6578c2ecf20Sopenharmony_ci 6588c2ecf20Sopenharmony_ci /* Allocate memory for KeyGen driver */ 6598c2ecf20Sopenharmony_ci keygen = kzalloc(sizeof(*keygen), GFP_KERNEL); 6608c2ecf20Sopenharmony_ci if (!keygen) 6618c2ecf20Sopenharmony_ci return NULL; 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_ci keygen->keygen_regs = keygen_regs; 6648c2ecf20Sopenharmony_ci 6658c2ecf20Sopenharmony_ci /* KeyGen initialization (for Master partition): 6668c2ecf20Sopenharmony_ci * Setup KeyGen registers 6678c2ecf20Sopenharmony_ci */ 6688c2ecf20Sopenharmony_ci iowrite32be(ENQUEUE_KG_DFLT_NIA, &keygen_regs->fmkg_gcr); 6698c2ecf20Sopenharmony_ci 6708c2ecf20Sopenharmony_ci iowrite32be(FM_EX_KG_DOUBLE_ECC | FM_EX_KG_KEYSIZE_OVERFLOW, 6718c2ecf20Sopenharmony_ci &keygen_regs->fmkg_eer); 6728c2ecf20Sopenharmony_ci 6738c2ecf20Sopenharmony_ci iowrite32be(0, &keygen_regs->fmkg_fdor); 6748c2ecf20Sopenharmony_ci iowrite32be(0, &keygen_regs->fmkg_gdv0r); 6758c2ecf20Sopenharmony_ci iowrite32be(0, &keygen_regs->fmkg_gdv1r); 6768c2ecf20Sopenharmony_ci 6778c2ecf20Sopenharmony_ci /* Clear binding between ports to schemes and classification plans 6788c2ecf20Sopenharmony_ci * so that all ports are not bound to any scheme/classification plan 6798c2ecf20Sopenharmony_ci */ 6808c2ecf20Sopenharmony_ci for (i = 0; i < FMAN_MAX_NUM_OF_HW_PORTS; i++) { 6818c2ecf20Sopenharmony_ci /* Clear all pe sp schemes registers */ 6828c2ecf20Sopenharmony_ci keygen_write_sp(keygen_regs, 0xffffffff, false); 6838c2ecf20Sopenharmony_ci ar = build_ar_bind_scheme(i, true); 6848c2ecf20Sopenharmony_ci keygen_write_ar_wait(keygen_regs, ar); 6858c2ecf20Sopenharmony_ci 6868c2ecf20Sopenharmony_ci /* Clear all pe cpp classification plans registers */ 6878c2ecf20Sopenharmony_ci keygen_write_cpp(keygen_regs, 0); 6888c2ecf20Sopenharmony_ci ar = build_ar_bind_cls_plan(i, true); 6898c2ecf20Sopenharmony_ci keygen_write_ar_wait(keygen_regs, ar); 6908c2ecf20Sopenharmony_ci } 6918c2ecf20Sopenharmony_ci 6928c2ecf20Sopenharmony_ci /* Enable all scheme interrupts */ 6938c2ecf20Sopenharmony_ci iowrite32be(0xFFFFFFFF, &keygen_regs->fmkg_seer); 6948c2ecf20Sopenharmony_ci iowrite32be(0xFFFFFFFF, &keygen_regs->fmkg_seeer); 6958c2ecf20Sopenharmony_ci 6968c2ecf20Sopenharmony_ci /* Enable KyeGen */ 6978c2ecf20Sopenharmony_ci iowrite32be(ioread32be(&keygen_regs->fmkg_gcr) | FM_KG_KGGCR_EN, 6988c2ecf20Sopenharmony_ci &keygen_regs->fmkg_gcr); 6998c2ecf20Sopenharmony_ci 7008c2ecf20Sopenharmony_ci return keygen; 7018c2ecf20Sopenharmony_ci} 7028c2ecf20Sopenharmony_ciEXPORT_SYMBOL(keygen_init); 7038c2ecf20Sopenharmony_ci 7048c2ecf20Sopenharmony_ci/* keygen_port_hashing_init 7058c2ecf20Sopenharmony_ci * 7068c2ecf20Sopenharmony_ci * Initializes a port for Rx Hashing with specified configuration parameters 7078c2ecf20Sopenharmony_ci * 7088c2ecf20Sopenharmony_ci * keygen: KeyGen handle 7098c2ecf20Sopenharmony_ci * hw_port_id: HW Port ID 7108c2ecf20Sopenharmony_ci * hash_base_fqid: Hashing Base FQID used for spreading 7118c2ecf20Sopenharmony_ci * hash_size: Hashing size 7128c2ecf20Sopenharmony_ci * 7138c2ecf20Sopenharmony_ci * Return: Zero for success or error code in case of failure 7148c2ecf20Sopenharmony_ci */ 7158c2ecf20Sopenharmony_ciint keygen_port_hashing_init(struct fman_keygen *keygen, u8 hw_port_id, 7168c2ecf20Sopenharmony_ci u32 hash_base_fqid, u32 hash_size) 7178c2ecf20Sopenharmony_ci{ 7188c2ecf20Sopenharmony_ci struct keygen_scheme *scheme; 7198c2ecf20Sopenharmony_ci u8 scheme_id; 7208c2ecf20Sopenharmony_ci int err; 7218c2ecf20Sopenharmony_ci 7228c2ecf20Sopenharmony_ci /* Validate Scheme configuration parameters */ 7238c2ecf20Sopenharmony_ci if (hash_base_fqid == 0 || (hash_base_fqid & ~0x00FFFFFF)) { 7248c2ecf20Sopenharmony_ci pr_err("Base FQID must be between 1 and 2^24-1\n"); 7258c2ecf20Sopenharmony_ci return -EINVAL; 7268c2ecf20Sopenharmony_ci } 7278c2ecf20Sopenharmony_ci if (hash_size == 0 || (hash_size & (hash_size - 1)) != 0) { 7288c2ecf20Sopenharmony_ci pr_err("Hash size must be power of two\n"); 7298c2ecf20Sopenharmony_ci return -EINVAL; 7308c2ecf20Sopenharmony_ci } 7318c2ecf20Sopenharmony_ci 7328c2ecf20Sopenharmony_ci /* Find a free scheme */ 7338c2ecf20Sopenharmony_ci err = get_free_scheme_id(keygen, &scheme_id); 7348c2ecf20Sopenharmony_ci if (err) { 7358c2ecf20Sopenharmony_ci pr_err("The maximum number of available Schemes has been exceeded\n"); 7368c2ecf20Sopenharmony_ci return -EINVAL; 7378c2ecf20Sopenharmony_ci } 7388c2ecf20Sopenharmony_ci 7398c2ecf20Sopenharmony_ci /* Create and configure Hard-Coded Scheme: */ 7408c2ecf20Sopenharmony_ci 7418c2ecf20Sopenharmony_ci scheme = get_scheme(keygen, scheme_id); 7428c2ecf20Sopenharmony_ci if (!scheme) { 7438c2ecf20Sopenharmony_ci pr_err("Requested Scheme does not exist\n"); 7448c2ecf20Sopenharmony_ci return -EINVAL; 7458c2ecf20Sopenharmony_ci } 7468c2ecf20Sopenharmony_ci if (scheme->used) { 7478c2ecf20Sopenharmony_ci pr_err("The requested Scheme is already used\n"); 7488c2ecf20Sopenharmony_ci return -EINVAL; 7498c2ecf20Sopenharmony_ci } 7508c2ecf20Sopenharmony_ci 7518c2ecf20Sopenharmony_ci /* Clear all scheme fields because the scheme may have been 7528c2ecf20Sopenharmony_ci * previously used 7538c2ecf20Sopenharmony_ci */ 7548c2ecf20Sopenharmony_ci memset(scheme, 0, sizeof(struct keygen_scheme)); 7558c2ecf20Sopenharmony_ci 7568c2ecf20Sopenharmony_ci /* Setup scheme: */ 7578c2ecf20Sopenharmony_ci scheme->hw_port_id = hw_port_id; 7588c2ecf20Sopenharmony_ci scheme->use_hashing = true; 7598c2ecf20Sopenharmony_ci scheme->base_fqid = hash_base_fqid; 7608c2ecf20Sopenharmony_ci scheme->hash_fqid_count = hash_size; 7618c2ecf20Sopenharmony_ci scheme->symmetric_hash = DEFAULT_SYMMETRIC_HASH; 7628c2ecf20Sopenharmony_ci scheme->hashShift = DEFAULT_HASH_SHIFT; 7638c2ecf20Sopenharmony_ci 7648c2ecf20Sopenharmony_ci /* All Schemes in hard-coded configuration 7658c2ecf20Sopenharmony_ci * are Indirect Schemes 7668c2ecf20Sopenharmony_ci */ 7678c2ecf20Sopenharmony_ci scheme->match_vector = 0; 7688c2ecf20Sopenharmony_ci 7698c2ecf20Sopenharmony_ci err = keygen_scheme_setup(keygen, scheme_id, true); 7708c2ecf20Sopenharmony_ci if (err != 0) { 7718c2ecf20Sopenharmony_ci pr_err("Scheme setup failed\n"); 7728c2ecf20Sopenharmony_ci return err; 7738c2ecf20Sopenharmony_ci } 7748c2ecf20Sopenharmony_ci 7758c2ecf20Sopenharmony_ci /* Bind Rx port to Scheme */ 7768c2ecf20Sopenharmony_ci err = keygen_bind_port_to_schemes(keygen, scheme_id, true); 7778c2ecf20Sopenharmony_ci if (err != 0) { 7788c2ecf20Sopenharmony_ci pr_err("Binding port to schemes failed\n"); 7798c2ecf20Sopenharmony_ci return err; 7808c2ecf20Sopenharmony_ci } 7818c2ecf20Sopenharmony_ci 7828c2ecf20Sopenharmony_ci return 0; 7838c2ecf20Sopenharmony_ci} 7848c2ecf20Sopenharmony_ciEXPORT_SYMBOL(keygen_port_hashing_init); 785