1*8585bdadSSean Anderson // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later
27472f4f2SIordache Florinel-R70177 /*
37472f4f2SIordache Florinel-R70177 * Copyright 2017 NXP
47472f4f2SIordache Florinel-R70177 */
57472f4f2SIordache Florinel-R70177
67472f4f2SIordache Florinel-R70177 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
77472f4f2SIordache Florinel-R70177
87472f4f2SIordache Florinel-R70177 #include <linux/slab.h>
97472f4f2SIordache Florinel-R70177
107472f4f2SIordache Florinel-R70177 #include "fman_keygen.h"
117472f4f2SIordache Florinel-R70177
127472f4f2SIordache Florinel-R70177 /* Maximum number of HW Ports */
137472f4f2SIordache Florinel-R70177 #define FMAN_MAX_NUM_OF_HW_PORTS 64
147472f4f2SIordache Florinel-R70177
157472f4f2SIordache Florinel-R70177 /* Maximum number of KeyGen Schemes */
167472f4f2SIordache Florinel-R70177 #define FM_KG_MAX_NUM_OF_SCHEMES 32
177472f4f2SIordache Florinel-R70177
187472f4f2SIordache Florinel-R70177 /* Number of generic KeyGen Generic Extract Command Registers */
197472f4f2SIordache Florinel-R70177 #define FM_KG_NUM_OF_GENERIC_REGS 8
207472f4f2SIordache Florinel-R70177
217472f4f2SIordache Florinel-R70177 /* Dummy port ID */
227472f4f2SIordache Florinel-R70177 #define DUMMY_PORT_ID 0
237472f4f2SIordache Florinel-R70177
247472f4f2SIordache Florinel-R70177 /* Select Scheme Value Register */
257472f4f2SIordache Florinel-R70177 #define KG_SCH_DEF_USE_KGSE_DV_0 2
267472f4f2SIordache Florinel-R70177 #define KG_SCH_DEF_USE_KGSE_DV_1 3
277472f4f2SIordache Florinel-R70177
287472f4f2SIordache Florinel-R70177 /* Registers Shifting values */
297472f4f2SIordache Florinel-R70177 #define FM_KG_KGAR_NUM_SHIFT 16
307472f4f2SIordache Florinel-R70177 #define KG_SCH_DEF_L4_PORT_SHIFT 8
317472f4f2SIordache Florinel-R70177 #define KG_SCH_DEF_IP_ADDR_SHIFT 18
327472f4f2SIordache Florinel-R70177 #define KG_SCH_HASH_CONFIG_SHIFT_SHIFT 24
337472f4f2SIordache Florinel-R70177
347472f4f2SIordache Florinel-R70177 /* KeyGen Registers bit field masks: */
357472f4f2SIordache Florinel-R70177
367472f4f2SIordache Florinel-R70177 /* Enable bit field mask for KeyGen General Configuration Register */
377472f4f2SIordache Florinel-R70177 #define FM_KG_KGGCR_EN 0x80000000
387472f4f2SIordache Florinel-R70177
397472f4f2SIordache Florinel-R70177 /* KeyGen Global Registers bit field masks */
407472f4f2SIordache Florinel-R70177 #define FM_KG_KGAR_GO 0x80000000
417472f4f2SIordache Florinel-R70177 #define FM_KG_KGAR_READ 0x40000000
427472f4f2SIordache Florinel-R70177 #define FM_KG_KGAR_WRITE 0x00000000
437472f4f2SIordache Florinel-R70177 #define FM_KG_KGAR_SEL_SCHEME_ENTRY 0x00000000
447472f4f2SIordache Florinel-R70177 #define FM_KG_KGAR_SCM_WSEL_UPDATE_CNT 0x00008000
457472f4f2SIordache Florinel-R70177
467472f4f2SIordache Florinel-R70177 #define FM_KG_KGAR_ERR 0x20000000
477472f4f2SIordache Florinel-R70177 #define FM_KG_KGAR_SEL_CLS_PLAN_ENTRY 0x01000000
487472f4f2SIordache Florinel-R70177 #define FM_KG_KGAR_SEL_PORT_ENTRY 0x02000000
497472f4f2SIordache Florinel-R70177 #define FM_KG_KGAR_SEL_PORT_WSEL_SP 0x00008000
507472f4f2SIordache Florinel-R70177 #define FM_KG_KGAR_SEL_PORT_WSEL_CPP 0x00004000
517472f4f2SIordache Florinel-R70177
527472f4f2SIordache Florinel-R70177 /* Error events exceptions */
537472f4f2SIordache Florinel-R70177 #define FM_EX_KG_DOUBLE_ECC 0x80000000
547472f4f2SIordache Florinel-R70177 #define FM_EX_KG_KEYSIZE_OVERFLOW 0x40000000
557472f4f2SIordache Florinel-R70177
567472f4f2SIordache Florinel-R70177 /* Scheme Registers bit field masks */
577472f4f2SIordache Florinel-R70177 #define KG_SCH_MODE_EN 0x80000000
587472f4f2SIordache Florinel-R70177 #define KG_SCH_VSP_NO_KSP_EN 0x80000000
597472f4f2SIordache Florinel-R70177 #define KG_SCH_HASH_CONFIG_SYM 0x40000000
607472f4f2SIordache Florinel-R70177
617472f4f2SIordache Florinel-R70177 /* Known Protocol field codes */
627472f4f2SIordache Florinel-R70177 #define KG_SCH_KN_PORT_ID 0x80000000
637472f4f2SIordache Florinel-R70177 #define KG_SCH_KN_MACDST 0x40000000
647472f4f2SIordache Florinel-R70177 #define KG_SCH_KN_MACSRC 0x20000000
657472f4f2SIordache Florinel-R70177 #define KG_SCH_KN_TCI1 0x10000000
667472f4f2SIordache Florinel-R70177 #define KG_SCH_KN_TCI2 0x08000000
677472f4f2SIordache Florinel-R70177 #define KG_SCH_KN_ETYPE 0x04000000
687472f4f2SIordache Florinel-R70177 #define KG_SCH_KN_PPPSID 0x02000000
697472f4f2SIordache Florinel-R70177 #define KG_SCH_KN_PPPID 0x01000000
707472f4f2SIordache Florinel-R70177 #define KG_SCH_KN_MPLS1 0x00800000
717472f4f2SIordache Florinel-R70177 #define KG_SCH_KN_MPLS2 0x00400000
727472f4f2SIordache Florinel-R70177 #define KG_SCH_KN_MPLS_LAST 0x00200000
737472f4f2SIordache Florinel-R70177 #define KG_SCH_KN_IPSRC1 0x00100000
747472f4f2SIordache Florinel-R70177 #define KG_SCH_KN_IPDST1 0x00080000
757472f4f2SIordache Florinel-R70177 #define KG_SCH_KN_PTYPE1 0x00040000
767472f4f2SIordache Florinel-R70177 #define KG_SCH_KN_IPTOS_TC1 0x00020000
777472f4f2SIordache Florinel-R70177 #define KG_SCH_KN_IPV6FL1 0x00010000
787472f4f2SIordache Florinel-R70177 #define KG_SCH_KN_IPSRC2 0x00008000
797472f4f2SIordache Florinel-R70177 #define KG_SCH_KN_IPDST2 0x00004000
807472f4f2SIordache Florinel-R70177 #define KG_SCH_KN_PTYPE2 0x00002000
817472f4f2SIordache Florinel-R70177 #define KG_SCH_KN_IPTOS_TC2 0x00001000
827472f4f2SIordache Florinel-R70177 #define KG_SCH_KN_IPV6FL2 0x00000800
837472f4f2SIordache Florinel-R70177 #define KG_SCH_KN_GREPTYPE 0x00000400
847472f4f2SIordache Florinel-R70177 #define KG_SCH_KN_IPSEC_SPI 0x00000200
857472f4f2SIordache Florinel-R70177 #define KG_SCH_KN_IPSEC_NH 0x00000100
867472f4f2SIordache Florinel-R70177 #define KG_SCH_KN_IPPID 0x00000080
877472f4f2SIordache Florinel-R70177 #define KG_SCH_KN_L4PSRC 0x00000004
887472f4f2SIordache Florinel-R70177 #define KG_SCH_KN_L4PDST 0x00000002
897472f4f2SIordache Florinel-R70177 #define KG_SCH_KN_TFLG 0x00000001
907472f4f2SIordache Florinel-R70177
917472f4f2SIordache Florinel-R70177 /* NIA values */
927472f4f2SIordache Florinel-R70177 #define NIA_ENG_BMI 0x00500000
937472f4f2SIordache Florinel-R70177 #define NIA_BMI_AC_ENQ_FRAME 0x00000002
947472f4f2SIordache Florinel-R70177 #define ENQUEUE_KG_DFLT_NIA (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME)
957472f4f2SIordache Florinel-R70177
967472f4f2SIordache Florinel-R70177 /* Hard-coded configuration:
977472f4f2SIordache Florinel-R70177 * These values are used as hard-coded values for KeyGen configuration
987472f4f2SIordache Florinel-R70177 * and they replace user selections for this hard-coded version
997472f4f2SIordache Florinel-R70177 */
1007472f4f2SIordache Florinel-R70177
1017472f4f2SIordache Florinel-R70177 /* Hash distribution shift */
1027472f4f2SIordache Florinel-R70177 #define DEFAULT_HASH_DIST_FQID_SHIFT 0
1037472f4f2SIordache Florinel-R70177
1047472f4f2SIordache Florinel-R70177 /* Hash shift */
1057472f4f2SIordache Florinel-R70177 #define DEFAULT_HASH_SHIFT 0
1067472f4f2SIordache Florinel-R70177
1077472f4f2SIordache Florinel-R70177 /* Symmetric hash usage:
1087472f4f2SIordache Florinel-R70177 * Warning:
1097472f4f2SIordache Florinel-R70177 * - the value for symmetric hash usage must be in accordance with hash
1107472f4f2SIordache Florinel-R70177 * key defined below
1117472f4f2SIordache Florinel-R70177 * - according to tests performed, spreading is not working if symmetric
1127472f4f2SIordache Florinel-R70177 * hash is set on true
1137472f4f2SIordache Florinel-R70177 * So ultimately symmetric hash functionality should be always disabled:
1147472f4f2SIordache Florinel-R70177 */
1157472f4f2SIordache Florinel-R70177 #define DEFAULT_SYMMETRIC_HASH false
1167472f4f2SIordache Florinel-R70177
1177472f4f2SIordache Florinel-R70177 /* Hash Key extraction fields: */
1187472f4f2SIordache Florinel-R70177 #define DEFAULT_HASH_KEY_EXTRACT_FIELDS \
1197472f4f2SIordache Florinel-R70177 (KG_SCH_KN_IPSRC1 | KG_SCH_KN_IPDST1 | \
120c7ae0925SMadalin Bucur KG_SCH_KN_L4PSRC | KG_SCH_KN_L4PDST | \
121c7ae0925SMadalin Bucur KG_SCH_KN_IPSEC_SPI)
1227472f4f2SIordache Florinel-R70177
1237472f4f2SIordache Florinel-R70177 /* Default values to be used as hash key in case IPv4 or L4 (TCP, UDP)
1247472f4f2SIordache Florinel-R70177 * don't exist in the frame
1257472f4f2SIordache Florinel-R70177 */
1267472f4f2SIordache Florinel-R70177 /* Default IPv4 address */
1277472f4f2SIordache Florinel-R70177 #define DEFAULT_HASH_KEY_IPv4_ADDR 0x0A0A0A0A
1287472f4f2SIordache Florinel-R70177 /* Default L4 port */
1297472f4f2SIordache Florinel-R70177 #define DEFAULT_HASH_KEY_L4_PORT 0x0B0B0B0B
1307472f4f2SIordache Florinel-R70177
1317472f4f2SIordache Florinel-R70177 /* KeyGen Memory Mapped Registers: */
1327472f4f2SIordache Florinel-R70177
1337472f4f2SIordache Florinel-R70177 /* Scheme Configuration RAM Registers */
1347472f4f2SIordache Florinel-R70177 struct fman_kg_scheme_regs {
1357472f4f2SIordache Florinel-R70177 u32 kgse_mode; /* 0x100: MODE */
1367472f4f2SIordache Florinel-R70177 u32 kgse_ekfc; /* 0x104: Extract Known Fields Command */
1377472f4f2SIordache Florinel-R70177 u32 kgse_ekdv; /* 0x108: Extract Known Default Value */
1387472f4f2SIordache Florinel-R70177 u32 kgse_bmch; /* 0x10C: Bit Mask Command High */
1397472f4f2SIordache Florinel-R70177 u32 kgse_bmcl; /* 0x110: Bit Mask Command Low */
1407472f4f2SIordache Florinel-R70177 u32 kgse_fqb; /* 0x114: Frame Queue Base */
1417472f4f2SIordache Florinel-R70177 u32 kgse_hc; /* 0x118: Hash Command */
1427472f4f2SIordache Florinel-R70177 u32 kgse_ppc; /* 0x11C: Policer Profile Command */
1437472f4f2SIordache Florinel-R70177 u32 kgse_gec[FM_KG_NUM_OF_GENERIC_REGS];
1447472f4f2SIordache Florinel-R70177 /* 0x120: Generic Extract Command */
1457472f4f2SIordache Florinel-R70177 u32 kgse_spc;
1467472f4f2SIordache Florinel-R70177 /* 0x140: KeyGen Scheme Entry Statistic Packet Counter */
1477472f4f2SIordache Florinel-R70177 u32 kgse_dv0; /* 0x144: KeyGen Scheme Entry Default Value 0 */
1487472f4f2SIordache Florinel-R70177 u32 kgse_dv1; /* 0x148: KeyGen Scheme Entry Default Value 1 */
1497472f4f2SIordache Florinel-R70177 u32 kgse_ccbs;
1507472f4f2SIordache Florinel-R70177 /* 0x14C: KeyGen Scheme Entry Coarse Classification Bit*/
1517472f4f2SIordache Florinel-R70177 u32 kgse_mv; /* 0x150: KeyGen Scheme Entry Match vector */
1527472f4f2SIordache Florinel-R70177 u32 kgse_om; /* 0x154: KeyGen Scheme Entry Operation Mode bits */
1537472f4f2SIordache Florinel-R70177 u32 kgse_vsp;
1547472f4f2SIordache Florinel-R70177 /* 0x158: KeyGen Scheme Entry Virtual Storage Profile */
1557472f4f2SIordache Florinel-R70177 };
1567472f4f2SIordache Florinel-R70177
1577472f4f2SIordache Florinel-R70177 /* Port Partition Configuration Registers */
1587472f4f2SIordache Florinel-R70177 struct fman_kg_pe_regs {
1597472f4f2SIordache Florinel-R70177 u32 fmkg_pe_sp; /* 0x100: KeyGen Port entry Scheme Partition */
1607472f4f2SIordache Florinel-R70177 u32 fmkg_pe_cpp;
1617472f4f2SIordache Florinel-R70177 /* 0x104: KeyGen Port Entry Classification Plan Partition */
1627472f4f2SIordache Florinel-R70177 };
1637472f4f2SIordache Florinel-R70177
1647472f4f2SIordache Florinel-R70177 /* General Configuration and Status Registers
1657472f4f2SIordache Florinel-R70177 * Global Statistic Counters
1667472f4f2SIordache Florinel-R70177 * KeyGen Global Registers
1677472f4f2SIordache Florinel-R70177 */
1687472f4f2SIordache Florinel-R70177 struct fman_kg_regs {
1697472f4f2SIordache Florinel-R70177 u32 fmkg_gcr; /* 0x000: KeyGen General Configuration Register */
1707472f4f2SIordache Florinel-R70177 u32 res004; /* 0x004: Reserved */
1717472f4f2SIordache Florinel-R70177 u32 res008; /* 0x008: Reserved */
1727472f4f2SIordache Florinel-R70177 u32 fmkg_eer; /* 0x00C: KeyGen Error Event Register */
1737472f4f2SIordache Florinel-R70177 u32 fmkg_eeer; /* 0x010: KeyGen Error Event Enable Register */
1747472f4f2SIordache Florinel-R70177 u32 res014; /* 0x014: Reserved */
1757472f4f2SIordache Florinel-R70177 u32 res018; /* 0x018: Reserved */
1767472f4f2SIordache Florinel-R70177 u32 fmkg_seer; /* 0x01C: KeyGen Scheme Error Event Register */
1777472f4f2SIordache Florinel-R70177 u32 fmkg_seeer; /* 0x020: KeyGen Scheme Error Event Enable Register */
1787472f4f2SIordache Florinel-R70177 u32 fmkg_gsr; /* 0x024: KeyGen Global Status Register */
1797472f4f2SIordache Florinel-R70177 u32 fmkg_tpc; /* 0x028: Total Packet Counter Register */
1807472f4f2SIordache Florinel-R70177 u32 fmkg_serc; /* 0x02C: Soft Error Capture Register */
1817472f4f2SIordache Florinel-R70177 u32 res030[4]; /* 0x030: Reserved */
1827472f4f2SIordache Florinel-R70177 u32 fmkg_fdor; /* 0x034: Frame Data Offset Register */
1837472f4f2SIordache Florinel-R70177 u32 fmkg_gdv0r; /* 0x038: Global Default Value Register 0 */
1847472f4f2SIordache Florinel-R70177 u32 fmkg_gdv1r; /* 0x03C: Global Default Value Register 1 */
1857472f4f2SIordache Florinel-R70177 u32 res04c[6]; /* 0x040: Reserved */
1867472f4f2SIordache Florinel-R70177 u32 fmkg_feer; /* 0x044: Force Error Event Register */
1877472f4f2SIordache Florinel-R70177 u32 res068[38]; /* 0x048: Reserved */
1887472f4f2SIordache Florinel-R70177 union {
1897472f4f2SIordache Florinel-R70177 u32 fmkg_indirect[63]; /* 0x100: Indirect Access Registers */
1907472f4f2SIordache Florinel-R70177 struct fman_kg_scheme_regs fmkg_sch; /* Scheme Registers */
1917472f4f2SIordache Florinel-R70177 struct fman_kg_pe_regs fmkg_pe; /* Port Partition Registers */
1927472f4f2SIordache Florinel-R70177 };
1937472f4f2SIordache Florinel-R70177 u32 fmkg_ar; /* 0x1FC: KeyGen Action Register */
1947472f4f2SIordache Florinel-R70177 };
1957472f4f2SIordache Florinel-R70177
1967472f4f2SIordache Florinel-R70177 /* KeyGen Scheme data */
1977472f4f2SIordache Florinel-R70177 struct keygen_scheme {
1987472f4f2SIordache Florinel-R70177 bool used; /* Specifies if this scheme is used */
1997472f4f2SIordache Florinel-R70177 u8 hw_port_id;
2007472f4f2SIordache Florinel-R70177 /* Hardware port ID
2017472f4f2SIordache Florinel-R70177 * schemes sharing between multiple ports is not
2027472f4f2SIordache Florinel-R70177 * currently supported
2037472f4f2SIordache Florinel-R70177 * so we have only one port id bound to a scheme
2047472f4f2SIordache Florinel-R70177 */
2057472f4f2SIordache Florinel-R70177 u32 base_fqid;
2067472f4f2SIordache Florinel-R70177 /* Base FQID:
2077472f4f2SIordache Florinel-R70177 * Must be between 1 and 2^24-1
2087472f4f2SIordache Florinel-R70177 * If hash is used and an even distribution is
2097472f4f2SIordache Florinel-R70177 * expected according to hash_fqid_count,
2107472f4f2SIordache Florinel-R70177 * base_fqid must be aligned to hash_fqid_count
2117472f4f2SIordache Florinel-R70177 */
2127472f4f2SIordache Florinel-R70177 u32 hash_fqid_count;
2137472f4f2SIordache Florinel-R70177 /* FQ range for hash distribution:
2147472f4f2SIordache Florinel-R70177 * Must be a power of 2
2157472f4f2SIordache Florinel-R70177 * Represents the range of queues for spreading
2167472f4f2SIordache Florinel-R70177 */
2177472f4f2SIordache Florinel-R70177 bool use_hashing; /* Usage of Hashing and spreading over FQ */
2187472f4f2SIordache Florinel-R70177 bool symmetric_hash; /* Symmetric Hash option usage */
2197472f4f2SIordache Florinel-R70177 u8 hashShift;
2207472f4f2SIordache Florinel-R70177 /* Hash result right shift.
2217472f4f2SIordache Florinel-R70177 * Select the 24 bits out of the 64 hash result.
2227472f4f2SIordache Florinel-R70177 * 0 means using the 24 LSB's, otherwise
2237472f4f2SIordache Florinel-R70177 * use the 24 LSB's after shifting right
2247472f4f2SIordache Florinel-R70177 */
2257472f4f2SIordache Florinel-R70177 u32 match_vector; /* Match Vector */
2267472f4f2SIordache Florinel-R70177 };
2277472f4f2SIordache Florinel-R70177
2287472f4f2SIordache Florinel-R70177 /* KeyGen driver data */
2297472f4f2SIordache Florinel-R70177 struct fman_keygen {
2307472f4f2SIordache Florinel-R70177 struct keygen_scheme schemes[FM_KG_MAX_NUM_OF_SCHEMES];
2317472f4f2SIordache Florinel-R70177 /* Array of schemes */
2327472f4f2SIordache Florinel-R70177 struct fman_kg_regs __iomem *keygen_regs; /* KeyGen registers */
2337472f4f2SIordache Florinel-R70177 };
2347472f4f2SIordache Florinel-R70177
2357472f4f2SIordache Florinel-R70177 /* keygen_write_ar_wait
2367472f4f2SIordache Florinel-R70177 *
2377472f4f2SIordache Florinel-R70177 * Write Action Register with specified value, wait for GO bit field to be
2387472f4f2SIordache Florinel-R70177 * idle and then read the error
2397472f4f2SIordache Florinel-R70177 *
2407472f4f2SIordache Florinel-R70177 * regs: KeyGen registers
2417472f4f2SIordache Florinel-R70177 * fmkg_ar: Action Register value
2427472f4f2SIordache Florinel-R70177 *
2437472f4f2SIordache Florinel-R70177 * Return: Zero for success or error code in case of failure
2447472f4f2SIordache Florinel-R70177 */
keygen_write_ar_wait(struct fman_kg_regs __iomem * regs,u32 fmkg_ar)2457472f4f2SIordache Florinel-R70177 static int keygen_write_ar_wait(struct fman_kg_regs __iomem *regs, u32 fmkg_ar)
2467472f4f2SIordache Florinel-R70177 {
2477472f4f2SIordache Florinel-R70177 iowrite32be(fmkg_ar, ®s->fmkg_ar);
2487472f4f2SIordache Florinel-R70177
2497472f4f2SIordache Florinel-R70177 /* Wait for GO bit field to be idle */
2507472f4f2SIordache Florinel-R70177 while (fmkg_ar & FM_KG_KGAR_GO)
2517472f4f2SIordache Florinel-R70177 fmkg_ar = ioread32be(®s->fmkg_ar);
2527472f4f2SIordache Florinel-R70177
2537472f4f2SIordache Florinel-R70177 if (fmkg_ar & FM_KG_KGAR_ERR)
2547472f4f2SIordache Florinel-R70177 return -EINVAL;
2557472f4f2SIordache Florinel-R70177
2567472f4f2SIordache Florinel-R70177 return 0;
2577472f4f2SIordache Florinel-R70177 }
2587472f4f2SIordache Florinel-R70177
2597472f4f2SIordache Florinel-R70177 /* build_ar_scheme
2607472f4f2SIordache Florinel-R70177 *
2617472f4f2SIordache Florinel-R70177 * Build Action Register value for scheme settings
2627472f4f2SIordache Florinel-R70177 *
2637472f4f2SIordache Florinel-R70177 * scheme_id: Scheme ID
2647472f4f2SIordache Florinel-R70177 * update_counter: update scheme counter
2657472f4f2SIordache Florinel-R70177 * write: true for action to write the scheme or false for read action
2667472f4f2SIordache Florinel-R70177 *
2677472f4f2SIordache Florinel-R70177 * Return: AR value
2687472f4f2SIordache Florinel-R70177 */
build_ar_scheme(u8 scheme_id,bool update_counter,bool write)2697472f4f2SIordache Florinel-R70177 static u32 build_ar_scheme(u8 scheme_id, bool update_counter, bool write)
2707472f4f2SIordache Florinel-R70177 {
2717472f4f2SIordache Florinel-R70177 u32 rw = (u32)(write ? FM_KG_KGAR_WRITE : FM_KG_KGAR_READ);
2727472f4f2SIordache Florinel-R70177
2737472f4f2SIordache Florinel-R70177 return (u32)(FM_KG_KGAR_GO |
2747472f4f2SIordache Florinel-R70177 rw |
2757472f4f2SIordache Florinel-R70177 FM_KG_KGAR_SEL_SCHEME_ENTRY |
2767472f4f2SIordache Florinel-R70177 DUMMY_PORT_ID |
2777472f4f2SIordache Florinel-R70177 ((u32)scheme_id << FM_KG_KGAR_NUM_SHIFT) |
2787472f4f2SIordache Florinel-R70177 (update_counter ? FM_KG_KGAR_SCM_WSEL_UPDATE_CNT : 0));
2797472f4f2SIordache Florinel-R70177 }
2807472f4f2SIordache Florinel-R70177
2817472f4f2SIordache Florinel-R70177 /* build_ar_bind_scheme
2827472f4f2SIordache Florinel-R70177 *
2837472f4f2SIordache Florinel-R70177 * Build Action Register value for port binding to schemes
2847472f4f2SIordache Florinel-R70177 *
2857472f4f2SIordache Florinel-R70177 * hwport_id: HW Port ID
2867472f4f2SIordache Florinel-R70177 * write: true for action to write the bind or false for read action
2877472f4f2SIordache Florinel-R70177 *
2887472f4f2SIordache Florinel-R70177 * Return: AR value
2897472f4f2SIordache Florinel-R70177 */
build_ar_bind_scheme(u8 hwport_id,bool write)2907472f4f2SIordache Florinel-R70177 static u32 build_ar_bind_scheme(u8 hwport_id, bool write)
2917472f4f2SIordache Florinel-R70177 {
2927472f4f2SIordache Florinel-R70177 u32 rw = write ? (u32)FM_KG_KGAR_WRITE : (u32)FM_KG_KGAR_READ;
2937472f4f2SIordache Florinel-R70177
2947472f4f2SIordache Florinel-R70177 return (u32)(FM_KG_KGAR_GO |
2957472f4f2SIordache Florinel-R70177 rw |
2967472f4f2SIordache Florinel-R70177 FM_KG_KGAR_SEL_PORT_ENTRY |
2977472f4f2SIordache Florinel-R70177 hwport_id |
2987472f4f2SIordache Florinel-R70177 FM_KG_KGAR_SEL_PORT_WSEL_SP);
2997472f4f2SIordache Florinel-R70177 }
3007472f4f2SIordache Florinel-R70177
3017472f4f2SIordache Florinel-R70177 /* keygen_write_sp
3027472f4f2SIordache Florinel-R70177 *
3037472f4f2SIordache Florinel-R70177 * Write Scheme Partition Register with specified value
3047472f4f2SIordache Florinel-R70177 *
3057472f4f2SIordache Florinel-R70177 * regs: KeyGen Registers
3067472f4f2SIordache Florinel-R70177 * sp: Scheme Partition register value
3077472f4f2SIordache Florinel-R70177 * add: true to add a scheme partition or false to clear
3087472f4f2SIordache Florinel-R70177 *
3097472f4f2SIordache Florinel-R70177 * Return: none
3107472f4f2SIordache Florinel-R70177 */
keygen_write_sp(struct fman_kg_regs __iomem * regs,u32 sp,bool add)3117472f4f2SIordache Florinel-R70177 static void keygen_write_sp(struct fman_kg_regs __iomem *regs, u32 sp, bool add)
3127472f4f2SIordache Florinel-R70177 {
3137472f4f2SIordache Florinel-R70177 u32 tmp;
3147472f4f2SIordache Florinel-R70177
3157472f4f2SIordache Florinel-R70177 tmp = ioread32be(®s->fmkg_pe.fmkg_pe_sp);
3167472f4f2SIordache Florinel-R70177
3177472f4f2SIordache Florinel-R70177 if (add)
3187472f4f2SIordache Florinel-R70177 tmp |= sp;
3197472f4f2SIordache Florinel-R70177 else
3207472f4f2SIordache Florinel-R70177 tmp &= ~sp;
3217472f4f2SIordache Florinel-R70177
3227472f4f2SIordache Florinel-R70177 iowrite32be(tmp, ®s->fmkg_pe.fmkg_pe_sp);
3237472f4f2SIordache Florinel-R70177 }
3247472f4f2SIordache Florinel-R70177
3257472f4f2SIordache Florinel-R70177 /* build_ar_bind_cls_plan
3267472f4f2SIordache Florinel-R70177 *
3277472f4f2SIordache Florinel-R70177 * Build Action Register value for Classification Plan
3287472f4f2SIordache Florinel-R70177 *
3297472f4f2SIordache Florinel-R70177 * hwport_id: HW Port ID
3307472f4f2SIordache Florinel-R70177 * write: true for action to write the CP or false for read action
3317472f4f2SIordache Florinel-R70177 *
3327472f4f2SIordache Florinel-R70177 * Return: AR value
3337472f4f2SIordache Florinel-R70177 */
build_ar_bind_cls_plan(u8 hwport_id,bool write)3347472f4f2SIordache Florinel-R70177 static u32 build_ar_bind_cls_plan(u8 hwport_id, bool write)
3357472f4f2SIordache Florinel-R70177 {
3367472f4f2SIordache Florinel-R70177 u32 rw = write ? (u32)FM_KG_KGAR_WRITE : (u32)FM_KG_KGAR_READ;
3377472f4f2SIordache Florinel-R70177
3387472f4f2SIordache Florinel-R70177 return (u32)(FM_KG_KGAR_GO |
3397472f4f2SIordache Florinel-R70177 rw |
3407472f4f2SIordache Florinel-R70177 FM_KG_KGAR_SEL_PORT_ENTRY |
3417472f4f2SIordache Florinel-R70177 hwport_id |
3427472f4f2SIordache Florinel-R70177 FM_KG_KGAR_SEL_PORT_WSEL_CPP);
3437472f4f2SIordache Florinel-R70177 }
3447472f4f2SIordache Florinel-R70177
3457472f4f2SIordache Florinel-R70177 /* keygen_write_cpp
3467472f4f2SIordache Florinel-R70177 *
3477472f4f2SIordache Florinel-R70177 * Write Classification Plan Partition Register with specified value
3487472f4f2SIordache Florinel-R70177 *
3497472f4f2SIordache Florinel-R70177 * regs: KeyGen Registers
3507472f4f2SIordache Florinel-R70177 * cpp: CPP register value
3517472f4f2SIordache Florinel-R70177 *
3527472f4f2SIordache Florinel-R70177 * Return: none
3537472f4f2SIordache Florinel-R70177 */
keygen_write_cpp(struct fman_kg_regs __iomem * regs,u32 cpp)3547472f4f2SIordache Florinel-R70177 static void keygen_write_cpp(struct fman_kg_regs __iomem *regs, u32 cpp)
3557472f4f2SIordache Florinel-R70177 {
3567472f4f2SIordache Florinel-R70177 iowrite32be(cpp, ®s->fmkg_pe.fmkg_pe_cpp);
3577472f4f2SIordache Florinel-R70177 }
3587472f4f2SIordache Florinel-R70177
3597472f4f2SIordache Florinel-R70177 /* keygen_write_scheme
3607472f4f2SIordache Florinel-R70177 *
3617472f4f2SIordache Florinel-R70177 * Write all Schemes Registers with specified values
3627472f4f2SIordache Florinel-R70177 *
3637472f4f2SIordache Florinel-R70177 * regs: KeyGen Registers
3647472f4f2SIordache Florinel-R70177 * scheme_id: Scheme ID
3657472f4f2SIordache Florinel-R70177 * scheme_regs: Scheme registers values desired to be written
3667472f4f2SIordache Florinel-R70177 * update_counter: update scheme counter
3677472f4f2SIordache Florinel-R70177 *
3687472f4f2SIordache Florinel-R70177 * Return: Zero for success or error code in case of failure
3697472f4f2SIordache Florinel-R70177 */
keygen_write_scheme(struct fman_kg_regs __iomem * regs,u8 scheme_id,struct fman_kg_scheme_regs * scheme_regs,bool update_counter)3707472f4f2SIordache Florinel-R70177 static int keygen_write_scheme(struct fman_kg_regs __iomem *regs, u8 scheme_id,
3717472f4f2SIordache Florinel-R70177 struct fman_kg_scheme_regs *scheme_regs,
3727472f4f2SIordache Florinel-R70177 bool update_counter)
3737472f4f2SIordache Florinel-R70177 {
3747472f4f2SIordache Florinel-R70177 u32 ar_reg;
3757472f4f2SIordache Florinel-R70177 int err, i;
3767472f4f2SIordache Florinel-R70177
3777472f4f2SIordache Florinel-R70177 /* Write indirect scheme registers */
3787472f4f2SIordache Florinel-R70177 iowrite32be(scheme_regs->kgse_mode, ®s->fmkg_sch.kgse_mode);
3797472f4f2SIordache Florinel-R70177 iowrite32be(scheme_regs->kgse_ekfc, ®s->fmkg_sch.kgse_ekfc);
3807472f4f2SIordache Florinel-R70177 iowrite32be(scheme_regs->kgse_ekdv, ®s->fmkg_sch.kgse_ekdv);
3817472f4f2SIordache Florinel-R70177 iowrite32be(scheme_regs->kgse_bmch, ®s->fmkg_sch.kgse_bmch);
3827472f4f2SIordache Florinel-R70177 iowrite32be(scheme_regs->kgse_bmcl, ®s->fmkg_sch.kgse_bmcl);
3837472f4f2SIordache Florinel-R70177 iowrite32be(scheme_regs->kgse_fqb, ®s->fmkg_sch.kgse_fqb);
3847472f4f2SIordache Florinel-R70177 iowrite32be(scheme_regs->kgse_hc, ®s->fmkg_sch.kgse_hc);
3857472f4f2SIordache Florinel-R70177 iowrite32be(scheme_regs->kgse_ppc, ®s->fmkg_sch.kgse_ppc);
3867472f4f2SIordache Florinel-R70177 iowrite32be(scheme_regs->kgse_spc, ®s->fmkg_sch.kgse_spc);
3877472f4f2SIordache Florinel-R70177 iowrite32be(scheme_regs->kgse_dv0, ®s->fmkg_sch.kgse_dv0);
3887472f4f2SIordache Florinel-R70177 iowrite32be(scheme_regs->kgse_dv1, ®s->fmkg_sch.kgse_dv1);
3897472f4f2SIordache Florinel-R70177 iowrite32be(scheme_regs->kgse_ccbs, ®s->fmkg_sch.kgse_ccbs);
3907472f4f2SIordache Florinel-R70177 iowrite32be(scheme_regs->kgse_mv, ®s->fmkg_sch.kgse_mv);
3917472f4f2SIordache Florinel-R70177 iowrite32be(scheme_regs->kgse_om, ®s->fmkg_sch.kgse_om);
3927472f4f2SIordache Florinel-R70177 iowrite32be(scheme_regs->kgse_vsp, ®s->fmkg_sch.kgse_vsp);
3937472f4f2SIordache Florinel-R70177
3947472f4f2SIordache Florinel-R70177 for (i = 0 ; i < FM_KG_NUM_OF_GENERIC_REGS ; i++)
3957472f4f2SIordache Florinel-R70177 iowrite32be(scheme_regs->kgse_gec[i],
3967472f4f2SIordache Florinel-R70177 ®s->fmkg_sch.kgse_gec[i]);
3977472f4f2SIordache Florinel-R70177
3987472f4f2SIordache Florinel-R70177 /* Write AR (Action register) */
3997472f4f2SIordache Florinel-R70177 ar_reg = build_ar_scheme(scheme_id, update_counter, true);
4007472f4f2SIordache Florinel-R70177 err = keygen_write_ar_wait(regs, ar_reg);
4017472f4f2SIordache Florinel-R70177 if (err != 0) {
4027472f4f2SIordache Florinel-R70177 pr_err("Writing Action Register failed\n");
4037472f4f2SIordache Florinel-R70177 return err;
4047472f4f2SIordache Florinel-R70177 }
4057472f4f2SIordache Florinel-R70177
4067472f4f2SIordache Florinel-R70177 return err;
4077472f4f2SIordache Florinel-R70177 }
4087472f4f2SIordache Florinel-R70177
4097472f4f2SIordache Florinel-R70177 /* get_free_scheme_id
4107472f4f2SIordache Florinel-R70177 *
4117472f4f2SIordache Florinel-R70177 * Find the first free scheme available to be used
4127472f4f2SIordache Florinel-R70177 *
4137472f4f2SIordache Florinel-R70177 * keygen: KeyGen handle
4147472f4f2SIordache Florinel-R70177 * scheme_id: pointer to scheme id
4157472f4f2SIordache Florinel-R70177 *
4167472f4f2SIordache Florinel-R70177 * Return: 0 on success, -EINVAL when the are no available free schemes
4177472f4f2SIordache Florinel-R70177 */
get_free_scheme_id(struct fman_keygen * keygen,u8 * scheme_id)4187472f4f2SIordache Florinel-R70177 static int get_free_scheme_id(struct fman_keygen *keygen, u8 *scheme_id)
4197472f4f2SIordache Florinel-R70177 {
4207472f4f2SIordache Florinel-R70177 u8 i;
4217472f4f2SIordache Florinel-R70177
4227472f4f2SIordache Florinel-R70177 for (i = 0; i < FM_KG_MAX_NUM_OF_SCHEMES; i++)
4237472f4f2SIordache Florinel-R70177 if (!keygen->schemes[i].used) {
4247472f4f2SIordache Florinel-R70177 *scheme_id = i;
4257472f4f2SIordache Florinel-R70177 return 0;
4267472f4f2SIordache Florinel-R70177 }
4277472f4f2SIordache Florinel-R70177
4287472f4f2SIordache Florinel-R70177 return -EINVAL;
4297472f4f2SIordache Florinel-R70177 }
4307472f4f2SIordache Florinel-R70177
4317472f4f2SIordache Florinel-R70177 /* get_scheme
4327472f4f2SIordache Florinel-R70177 *
4337472f4f2SIordache Florinel-R70177 * Provides the scheme for specified ID
4347472f4f2SIordache Florinel-R70177 *
4357472f4f2SIordache Florinel-R70177 * keygen: KeyGen handle
4367472f4f2SIordache Florinel-R70177 * scheme_id: Scheme ID
4377472f4f2SIordache Florinel-R70177 *
4387472f4f2SIordache Florinel-R70177 * Return: handle to required scheme
4397472f4f2SIordache Florinel-R70177 */
get_scheme(struct fman_keygen * keygen,u8 scheme_id)4407472f4f2SIordache Florinel-R70177 static struct keygen_scheme *get_scheme(struct fman_keygen *keygen,
4417472f4f2SIordache Florinel-R70177 u8 scheme_id)
4427472f4f2SIordache Florinel-R70177 {
4437472f4f2SIordache Florinel-R70177 if (scheme_id >= FM_KG_MAX_NUM_OF_SCHEMES)
4447472f4f2SIordache Florinel-R70177 return NULL;
4457472f4f2SIordache Florinel-R70177 return &keygen->schemes[scheme_id];
4467472f4f2SIordache Florinel-R70177 }
4477472f4f2SIordache Florinel-R70177
4487472f4f2SIordache Florinel-R70177 /* keygen_bind_port_to_schemes
4497472f4f2SIordache Florinel-R70177 *
4507472f4f2SIordache Florinel-R70177 * Bind the port to schemes
4517472f4f2SIordache Florinel-R70177 *
4527472f4f2SIordache Florinel-R70177 * keygen: KeyGen handle
4537472f4f2SIordache Florinel-R70177 * scheme_id: id of the scheme to bind to
4547472f4f2SIordache Florinel-R70177 * bind: true to bind the port or false to unbind it
4557472f4f2SIordache Florinel-R70177 *
4567472f4f2SIordache Florinel-R70177 * Return: Zero for success or error code in case of failure
4577472f4f2SIordache Florinel-R70177 */
keygen_bind_port_to_schemes(struct fman_keygen * keygen,u8 scheme_id,bool bind)4587472f4f2SIordache Florinel-R70177 static int keygen_bind_port_to_schemes(struct fman_keygen *keygen,
4597472f4f2SIordache Florinel-R70177 u8 scheme_id,
4607472f4f2SIordache Florinel-R70177 bool bind)
4617472f4f2SIordache Florinel-R70177 {
4627472f4f2SIordache Florinel-R70177 struct fman_kg_regs __iomem *keygen_regs = keygen->keygen_regs;
4637472f4f2SIordache Florinel-R70177 struct keygen_scheme *scheme;
4647472f4f2SIordache Florinel-R70177 u32 ar_reg;
4657472f4f2SIordache Florinel-R70177 u32 schemes_vector = 0;
4667472f4f2SIordache Florinel-R70177 int err;
4677472f4f2SIordache Florinel-R70177
4687472f4f2SIordache Florinel-R70177 scheme = get_scheme(keygen, scheme_id);
4697472f4f2SIordache Florinel-R70177 if (!scheme) {
4707472f4f2SIordache Florinel-R70177 pr_err("Requested Scheme does not exist\n");
4717472f4f2SIordache Florinel-R70177 return -EINVAL;
4727472f4f2SIordache Florinel-R70177 }
4737472f4f2SIordache Florinel-R70177 if (!scheme->used) {
4747472f4f2SIordache Florinel-R70177 pr_err("Cannot bind port to an invalid scheme\n");
4757472f4f2SIordache Florinel-R70177 return -EINVAL;
4767472f4f2SIordache Florinel-R70177 }
4777472f4f2SIordache Florinel-R70177
4787472f4f2SIordache Florinel-R70177 schemes_vector |= 1 << (31 - scheme_id);
4797472f4f2SIordache Florinel-R70177
4807472f4f2SIordache Florinel-R70177 ar_reg = build_ar_bind_scheme(scheme->hw_port_id, false);
4817472f4f2SIordache Florinel-R70177 err = keygen_write_ar_wait(keygen_regs, ar_reg);
4827472f4f2SIordache Florinel-R70177 if (err != 0) {
4837472f4f2SIordache Florinel-R70177 pr_err("Reading Action Register failed\n");
4847472f4f2SIordache Florinel-R70177 return err;
4857472f4f2SIordache Florinel-R70177 }
4867472f4f2SIordache Florinel-R70177
4877472f4f2SIordache Florinel-R70177 keygen_write_sp(keygen_regs, schemes_vector, bind);
4887472f4f2SIordache Florinel-R70177
4897472f4f2SIordache Florinel-R70177 ar_reg = build_ar_bind_scheme(scheme->hw_port_id, true);
4907472f4f2SIordache Florinel-R70177 err = keygen_write_ar_wait(keygen_regs, ar_reg);
4917472f4f2SIordache Florinel-R70177 if (err != 0) {
4927472f4f2SIordache Florinel-R70177 pr_err("Writing Action Register failed\n");
4937472f4f2SIordache Florinel-R70177 return err;
4947472f4f2SIordache Florinel-R70177 }
4957472f4f2SIordache Florinel-R70177
4967472f4f2SIordache Florinel-R70177 return 0;
4977472f4f2SIordache Florinel-R70177 }
4987472f4f2SIordache Florinel-R70177
4997472f4f2SIordache Florinel-R70177 /* keygen_scheme_setup
5007472f4f2SIordache Florinel-R70177 *
5017472f4f2SIordache Florinel-R70177 * Setup the scheme according to required configuration
5027472f4f2SIordache Florinel-R70177 *
5037472f4f2SIordache Florinel-R70177 * keygen: KeyGen handle
5047472f4f2SIordache Florinel-R70177 * scheme_id: scheme ID
5057472f4f2SIordache Florinel-R70177 * enable: true to enable scheme or false to disable it
5067472f4f2SIordache Florinel-R70177 *
5077472f4f2SIordache Florinel-R70177 * Return: Zero for success or error code in case of failure
5087472f4f2SIordache Florinel-R70177 */
keygen_scheme_setup(struct fman_keygen * keygen,u8 scheme_id,bool enable)5097472f4f2SIordache Florinel-R70177 static int keygen_scheme_setup(struct fman_keygen *keygen, u8 scheme_id,
5107472f4f2SIordache Florinel-R70177 bool enable)
5117472f4f2SIordache Florinel-R70177 {
5127472f4f2SIordache Florinel-R70177 struct fman_kg_regs __iomem *keygen_regs = keygen->keygen_regs;
5137472f4f2SIordache Florinel-R70177 struct fman_kg_scheme_regs scheme_regs;
5147472f4f2SIordache Florinel-R70177 struct keygen_scheme *scheme;
5157472f4f2SIordache Florinel-R70177 u32 tmp_reg;
5167472f4f2SIordache Florinel-R70177 int err;
5177472f4f2SIordache Florinel-R70177
5187472f4f2SIordache Florinel-R70177 scheme = get_scheme(keygen, scheme_id);
5197472f4f2SIordache Florinel-R70177 if (!scheme) {
5207472f4f2SIordache Florinel-R70177 pr_err("Requested Scheme does not exist\n");
5217472f4f2SIordache Florinel-R70177 return -EINVAL;
5227472f4f2SIordache Florinel-R70177 }
5237472f4f2SIordache Florinel-R70177 if (enable && scheme->used) {
5247472f4f2SIordache Florinel-R70177 pr_err("The requested Scheme is already used\n");
5257472f4f2SIordache Florinel-R70177 return -EINVAL;
5267472f4f2SIordache Florinel-R70177 }
5277472f4f2SIordache Florinel-R70177
5287472f4f2SIordache Florinel-R70177 /* Clear scheme registers */
5297472f4f2SIordache Florinel-R70177 memset(&scheme_regs, 0, sizeof(struct fman_kg_scheme_regs));
5307472f4f2SIordache Florinel-R70177
5317472f4f2SIordache Florinel-R70177 /* Setup all scheme registers: */
5327472f4f2SIordache Florinel-R70177 tmp_reg = 0;
5337472f4f2SIordache Florinel-R70177
5347472f4f2SIordache Florinel-R70177 if (enable) {
5357472f4f2SIordache Florinel-R70177 /* Enable Scheme */
5367472f4f2SIordache Florinel-R70177 tmp_reg |= KG_SCH_MODE_EN;
5377472f4f2SIordache Florinel-R70177 /* Enqueue frame NIA */
5387472f4f2SIordache Florinel-R70177 tmp_reg |= ENQUEUE_KG_DFLT_NIA;
5397472f4f2SIordache Florinel-R70177 }
5407472f4f2SIordache Florinel-R70177
5417472f4f2SIordache Florinel-R70177 scheme_regs.kgse_mode = tmp_reg;
5427472f4f2SIordache Florinel-R70177
5437472f4f2SIordache Florinel-R70177 scheme_regs.kgse_mv = scheme->match_vector;
5447472f4f2SIordache Florinel-R70177
5457472f4f2SIordache Florinel-R70177 /* Scheme don't override StorageProfile:
5467472f4f2SIordache Florinel-R70177 * valid only for DPAA_VERSION >= 11
5477472f4f2SIordache Florinel-R70177 */
5487472f4f2SIordache Florinel-R70177 scheme_regs.kgse_vsp = KG_SCH_VSP_NO_KSP_EN;
5497472f4f2SIordache Florinel-R70177
5507472f4f2SIordache Florinel-R70177 /* Configure Hard-Coded Rx Hashing: */
5517472f4f2SIordache Florinel-R70177
5527472f4f2SIordache Florinel-R70177 if (scheme->use_hashing) {
5537472f4f2SIordache Florinel-R70177 /* configure kgse_ekfc */
5547472f4f2SIordache Florinel-R70177 scheme_regs.kgse_ekfc = DEFAULT_HASH_KEY_EXTRACT_FIELDS;
5557472f4f2SIordache Florinel-R70177
5567472f4f2SIordache Florinel-R70177 /* configure kgse_ekdv */
5577472f4f2SIordache Florinel-R70177 tmp_reg = 0;
5587472f4f2SIordache Florinel-R70177 tmp_reg |= (KG_SCH_DEF_USE_KGSE_DV_0 <<
5597472f4f2SIordache Florinel-R70177 KG_SCH_DEF_IP_ADDR_SHIFT);
5607472f4f2SIordache Florinel-R70177 tmp_reg |= (KG_SCH_DEF_USE_KGSE_DV_1 <<
5617472f4f2SIordache Florinel-R70177 KG_SCH_DEF_L4_PORT_SHIFT);
5627472f4f2SIordache Florinel-R70177 scheme_regs.kgse_ekdv = tmp_reg;
5637472f4f2SIordache Florinel-R70177
5647472f4f2SIordache Florinel-R70177 /* configure kgse_dv0 */
5657472f4f2SIordache Florinel-R70177 scheme_regs.kgse_dv0 = DEFAULT_HASH_KEY_IPv4_ADDR;
5667472f4f2SIordache Florinel-R70177 /* configure kgse_dv1 */
5677472f4f2SIordache Florinel-R70177 scheme_regs.kgse_dv1 = DEFAULT_HASH_KEY_L4_PORT;
5687472f4f2SIordache Florinel-R70177
5697472f4f2SIordache Florinel-R70177 /* configure kgse_hc */
5707472f4f2SIordache Florinel-R70177 tmp_reg = 0;
5717472f4f2SIordache Florinel-R70177 tmp_reg |= ((scheme->hash_fqid_count - 1) <<
5727472f4f2SIordache Florinel-R70177 DEFAULT_HASH_DIST_FQID_SHIFT);
5737472f4f2SIordache Florinel-R70177 tmp_reg |= scheme->hashShift << KG_SCH_HASH_CONFIG_SHIFT_SHIFT;
5747472f4f2SIordache Florinel-R70177
5757472f4f2SIordache Florinel-R70177 if (scheme->symmetric_hash) {
5767472f4f2SIordache Florinel-R70177 /* Normally extraction key should be verified if
5777472f4f2SIordache Florinel-R70177 * complies with symmetric hash
5787472f4f2SIordache Florinel-R70177 * But because extraction is hard-coded, we are sure
5797472f4f2SIordache Florinel-R70177 * the key is symmetric
5807472f4f2SIordache Florinel-R70177 */
5817472f4f2SIordache Florinel-R70177 tmp_reg |= KG_SCH_HASH_CONFIG_SYM;
5827472f4f2SIordache Florinel-R70177 }
5837472f4f2SIordache Florinel-R70177 scheme_regs.kgse_hc = tmp_reg;
5847472f4f2SIordache Florinel-R70177 } else {
5857472f4f2SIordache Florinel-R70177 scheme_regs.kgse_ekfc = 0;
5867472f4f2SIordache Florinel-R70177 scheme_regs.kgse_hc = 0;
5877472f4f2SIordache Florinel-R70177 scheme_regs.kgse_ekdv = 0;
5887472f4f2SIordache Florinel-R70177 scheme_regs.kgse_dv0 = 0;
5897472f4f2SIordache Florinel-R70177 scheme_regs.kgse_dv1 = 0;
5907472f4f2SIordache Florinel-R70177 }
5917472f4f2SIordache Florinel-R70177
5927472f4f2SIordache Florinel-R70177 /* configure kgse_fqb: Scheme FQID base */
5937472f4f2SIordache Florinel-R70177 tmp_reg = 0;
5947472f4f2SIordache Florinel-R70177 tmp_reg |= scheme->base_fqid;
5957472f4f2SIordache Florinel-R70177 scheme_regs.kgse_fqb = tmp_reg;
5967472f4f2SIordache Florinel-R70177
5977472f4f2SIordache Florinel-R70177 /* features not used by hard-coded configuration */
5987472f4f2SIordache Florinel-R70177 scheme_regs.kgse_bmch = 0;
5997472f4f2SIordache Florinel-R70177 scheme_regs.kgse_bmcl = 0;
6007472f4f2SIordache Florinel-R70177 scheme_regs.kgse_spc = 0;
6017472f4f2SIordache Florinel-R70177
6027472f4f2SIordache Florinel-R70177 /* Write scheme registers */
6037472f4f2SIordache Florinel-R70177 err = keygen_write_scheme(keygen_regs, scheme_id, &scheme_regs, true);
6047472f4f2SIordache Florinel-R70177 if (err != 0) {
6057472f4f2SIordache Florinel-R70177 pr_err("Writing scheme registers failed\n");
6067472f4f2SIordache Florinel-R70177 return err;
6077472f4f2SIordache Florinel-R70177 }
6087472f4f2SIordache Florinel-R70177
6097472f4f2SIordache Florinel-R70177 /* Update used field for Scheme */
6107472f4f2SIordache Florinel-R70177 scheme->used = enable;
6117472f4f2SIordache Florinel-R70177
6127472f4f2SIordache Florinel-R70177 return 0;
6137472f4f2SIordache Florinel-R70177 }
6147472f4f2SIordache Florinel-R70177
6157472f4f2SIordache Florinel-R70177 /* keygen_init
6167472f4f2SIordache Florinel-R70177 *
6177472f4f2SIordache Florinel-R70177 * KeyGen initialization:
6187472f4f2SIordache Florinel-R70177 * Initializes and enables KeyGen, allocate driver memory, setup registers,
6197472f4f2SIordache Florinel-R70177 * clear port bindings, invalidate all schemes
6207472f4f2SIordache Florinel-R70177 *
6217472f4f2SIordache Florinel-R70177 * keygen_regs: KeyGen registers base address
6227472f4f2SIordache Florinel-R70177 *
6237472f4f2SIordache Florinel-R70177 * Return: Handle to KeyGen driver
6247472f4f2SIordache Florinel-R70177 */
keygen_init(struct fman_kg_regs __iomem * keygen_regs)6257472f4f2SIordache Florinel-R70177 struct fman_keygen *keygen_init(struct fman_kg_regs __iomem *keygen_regs)
6267472f4f2SIordache Florinel-R70177 {
6277472f4f2SIordache Florinel-R70177 struct fman_keygen *keygen;
6287472f4f2SIordache Florinel-R70177 u32 ar;
6297472f4f2SIordache Florinel-R70177 int i;
6307472f4f2SIordache Florinel-R70177
6317472f4f2SIordache Florinel-R70177 /* Allocate memory for KeyGen driver */
6327472f4f2SIordache Florinel-R70177 keygen = kzalloc(sizeof(*keygen), GFP_KERNEL);
6337472f4f2SIordache Florinel-R70177 if (!keygen)
6347472f4f2SIordache Florinel-R70177 return NULL;
6357472f4f2SIordache Florinel-R70177
6367472f4f2SIordache Florinel-R70177 keygen->keygen_regs = keygen_regs;
6377472f4f2SIordache Florinel-R70177
6387472f4f2SIordache Florinel-R70177 /* KeyGen initialization (for Master partition):
6397472f4f2SIordache Florinel-R70177 * Setup KeyGen registers
6407472f4f2SIordache Florinel-R70177 */
6417472f4f2SIordache Florinel-R70177 iowrite32be(ENQUEUE_KG_DFLT_NIA, &keygen_regs->fmkg_gcr);
6427472f4f2SIordache Florinel-R70177
6437472f4f2SIordache Florinel-R70177 iowrite32be(FM_EX_KG_DOUBLE_ECC | FM_EX_KG_KEYSIZE_OVERFLOW,
6447472f4f2SIordache Florinel-R70177 &keygen_regs->fmkg_eer);
6457472f4f2SIordache Florinel-R70177
6467472f4f2SIordache Florinel-R70177 iowrite32be(0, &keygen_regs->fmkg_fdor);
6477472f4f2SIordache Florinel-R70177 iowrite32be(0, &keygen_regs->fmkg_gdv0r);
6487472f4f2SIordache Florinel-R70177 iowrite32be(0, &keygen_regs->fmkg_gdv1r);
6497472f4f2SIordache Florinel-R70177
6507472f4f2SIordache Florinel-R70177 /* Clear binding between ports to schemes and classification plans
6517472f4f2SIordache Florinel-R70177 * so that all ports are not bound to any scheme/classification plan
6527472f4f2SIordache Florinel-R70177 */
6537472f4f2SIordache Florinel-R70177 for (i = 0; i < FMAN_MAX_NUM_OF_HW_PORTS; i++) {
6547472f4f2SIordache Florinel-R70177 /* Clear all pe sp schemes registers */
6557472f4f2SIordache Florinel-R70177 keygen_write_sp(keygen_regs, 0xffffffff, false);
6567472f4f2SIordache Florinel-R70177 ar = build_ar_bind_scheme(i, true);
6577472f4f2SIordache Florinel-R70177 keygen_write_ar_wait(keygen_regs, ar);
6587472f4f2SIordache Florinel-R70177
6597472f4f2SIordache Florinel-R70177 /* Clear all pe cpp classification plans registers */
6607472f4f2SIordache Florinel-R70177 keygen_write_cpp(keygen_regs, 0);
6617472f4f2SIordache Florinel-R70177 ar = build_ar_bind_cls_plan(i, true);
6627472f4f2SIordache Florinel-R70177 keygen_write_ar_wait(keygen_regs, ar);
6637472f4f2SIordache Florinel-R70177 }
6647472f4f2SIordache Florinel-R70177
6657472f4f2SIordache Florinel-R70177 /* Enable all scheme interrupts */
6667472f4f2SIordache Florinel-R70177 iowrite32be(0xFFFFFFFF, &keygen_regs->fmkg_seer);
6677472f4f2SIordache Florinel-R70177 iowrite32be(0xFFFFFFFF, &keygen_regs->fmkg_seeer);
6687472f4f2SIordache Florinel-R70177
6697472f4f2SIordache Florinel-R70177 /* Enable KyeGen */
6707472f4f2SIordache Florinel-R70177 iowrite32be(ioread32be(&keygen_regs->fmkg_gcr) | FM_KG_KGGCR_EN,
6717472f4f2SIordache Florinel-R70177 &keygen_regs->fmkg_gcr);
6727472f4f2SIordache Florinel-R70177
6737472f4f2SIordache Florinel-R70177 return keygen;
6747472f4f2SIordache Florinel-R70177 }
6757472f4f2SIordache Florinel-R70177 EXPORT_SYMBOL(keygen_init);
6767472f4f2SIordache Florinel-R70177
6777472f4f2SIordache Florinel-R70177 /* keygen_port_hashing_init
6787472f4f2SIordache Florinel-R70177 *
6797472f4f2SIordache Florinel-R70177 * Initializes a port for Rx Hashing with specified configuration parameters
6807472f4f2SIordache Florinel-R70177 *
6817472f4f2SIordache Florinel-R70177 * keygen: KeyGen handle
6827472f4f2SIordache Florinel-R70177 * hw_port_id: HW Port ID
6837472f4f2SIordache Florinel-R70177 * hash_base_fqid: Hashing Base FQID used for spreading
6847472f4f2SIordache Florinel-R70177 * hash_size: Hashing size
6857472f4f2SIordache Florinel-R70177 *
6867472f4f2SIordache Florinel-R70177 * Return: Zero for success or error code in case of failure
6877472f4f2SIordache Florinel-R70177 */
keygen_port_hashing_init(struct fman_keygen * keygen,u8 hw_port_id,u32 hash_base_fqid,u32 hash_size)6887472f4f2SIordache Florinel-R70177 int keygen_port_hashing_init(struct fman_keygen *keygen, u8 hw_port_id,
6897472f4f2SIordache Florinel-R70177 u32 hash_base_fqid, u32 hash_size)
6907472f4f2SIordache Florinel-R70177 {
6917472f4f2SIordache Florinel-R70177 struct keygen_scheme *scheme;
6927472f4f2SIordache Florinel-R70177 u8 scheme_id;
6937472f4f2SIordache Florinel-R70177 int err;
6947472f4f2SIordache Florinel-R70177
6957472f4f2SIordache Florinel-R70177 /* Validate Scheme configuration parameters */
6967472f4f2SIordache Florinel-R70177 if (hash_base_fqid == 0 || (hash_base_fqid & ~0x00FFFFFF)) {
6977472f4f2SIordache Florinel-R70177 pr_err("Base FQID must be between 1 and 2^24-1\n");
6987472f4f2SIordache Florinel-R70177 return -EINVAL;
6997472f4f2SIordache Florinel-R70177 }
7007472f4f2SIordache Florinel-R70177 if (hash_size == 0 || (hash_size & (hash_size - 1)) != 0) {
7017472f4f2SIordache Florinel-R70177 pr_err("Hash size must be power of two\n");
7027472f4f2SIordache Florinel-R70177 return -EINVAL;
7037472f4f2SIordache Florinel-R70177 }
7047472f4f2SIordache Florinel-R70177
7057472f4f2SIordache Florinel-R70177 /* Find a free scheme */
7067472f4f2SIordache Florinel-R70177 err = get_free_scheme_id(keygen, &scheme_id);
7077472f4f2SIordache Florinel-R70177 if (err) {
7087472f4f2SIordache Florinel-R70177 pr_err("The maximum number of available Schemes has been exceeded\n");
7097472f4f2SIordache Florinel-R70177 return -EINVAL;
7107472f4f2SIordache Florinel-R70177 }
7117472f4f2SIordache Florinel-R70177
7127472f4f2SIordache Florinel-R70177 /* Create and configure Hard-Coded Scheme: */
7137472f4f2SIordache Florinel-R70177
7147472f4f2SIordache Florinel-R70177 scheme = get_scheme(keygen, scheme_id);
7157472f4f2SIordache Florinel-R70177 if (!scheme) {
7167472f4f2SIordache Florinel-R70177 pr_err("Requested Scheme does not exist\n");
7177472f4f2SIordache Florinel-R70177 return -EINVAL;
7187472f4f2SIordache Florinel-R70177 }
7197472f4f2SIordache Florinel-R70177 if (scheme->used) {
7207472f4f2SIordache Florinel-R70177 pr_err("The requested Scheme is already used\n");
7217472f4f2SIordache Florinel-R70177 return -EINVAL;
7227472f4f2SIordache Florinel-R70177 }
7237472f4f2SIordache Florinel-R70177
7247472f4f2SIordache Florinel-R70177 /* Clear all scheme fields because the scheme may have been
7257472f4f2SIordache Florinel-R70177 * previously used
7267472f4f2SIordache Florinel-R70177 */
7277472f4f2SIordache Florinel-R70177 memset(scheme, 0, sizeof(struct keygen_scheme));
7287472f4f2SIordache Florinel-R70177
7297472f4f2SIordache Florinel-R70177 /* Setup scheme: */
7307472f4f2SIordache Florinel-R70177 scheme->hw_port_id = hw_port_id;
7317472f4f2SIordache Florinel-R70177 scheme->use_hashing = true;
7327472f4f2SIordache Florinel-R70177 scheme->base_fqid = hash_base_fqid;
7337472f4f2SIordache Florinel-R70177 scheme->hash_fqid_count = hash_size;
7347472f4f2SIordache Florinel-R70177 scheme->symmetric_hash = DEFAULT_SYMMETRIC_HASH;
7357472f4f2SIordache Florinel-R70177 scheme->hashShift = DEFAULT_HASH_SHIFT;
7367472f4f2SIordache Florinel-R70177
7377472f4f2SIordache Florinel-R70177 /* All Schemes in hard-coded configuration
7387472f4f2SIordache Florinel-R70177 * are Indirect Schemes
7397472f4f2SIordache Florinel-R70177 */
7407472f4f2SIordache Florinel-R70177 scheme->match_vector = 0;
7417472f4f2SIordache Florinel-R70177
7427472f4f2SIordache Florinel-R70177 err = keygen_scheme_setup(keygen, scheme_id, true);
7437472f4f2SIordache Florinel-R70177 if (err != 0) {
7447472f4f2SIordache Florinel-R70177 pr_err("Scheme setup failed\n");
7457472f4f2SIordache Florinel-R70177 return err;
7467472f4f2SIordache Florinel-R70177 }
7477472f4f2SIordache Florinel-R70177
7487472f4f2SIordache Florinel-R70177 /* Bind Rx port to Scheme */
7497472f4f2SIordache Florinel-R70177 err = keygen_bind_port_to_schemes(keygen, scheme_id, true);
7507472f4f2SIordache Florinel-R70177 if (err != 0) {
7517472f4f2SIordache Florinel-R70177 pr_err("Binding port to schemes failed\n");
7527472f4f2SIordache Florinel-R70177 return err;
7537472f4f2SIordache Florinel-R70177 }
7547472f4f2SIordache Florinel-R70177
7557472f4f2SIordache Florinel-R70177 return 0;
7567472f4f2SIordache Florinel-R70177 }
7577472f4f2SIordache Florinel-R70177 EXPORT_SYMBOL(keygen_port_hashing_init);
758