xref: /OK3568_Linux_fs/kernel/drivers/net/ethernet/freescale/fman/fman_keygen.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright 2017 NXP
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Redistribution and use in source and binary forms, with or without
5*4882a593Smuzhiyun  * modification, are permitted provided that the following conditions are met:
6*4882a593Smuzhiyun  *     * Redistributions of source code must retain the above copyright
7*4882a593Smuzhiyun  *       notice, this list of conditions and the following disclaimer.
8*4882a593Smuzhiyun  *     * Redistributions in binary form must reproduce the above copyright
9*4882a593Smuzhiyun  *       notice, this list of conditions and the following disclaimer in the
10*4882a593Smuzhiyun  *       documentation and/or other materials provided with the distribution.
11*4882a593Smuzhiyun  *     * Neither the name of NXP nor the
12*4882a593Smuzhiyun  *       names of its contributors may be used to endorse or promote products
13*4882a593Smuzhiyun  *       derived from this software without specific prior written permission.
14*4882a593Smuzhiyun  *
15*4882a593Smuzhiyun  *
16*4882a593Smuzhiyun  * ALTERNATIVELY, this software may be distributed under the terms of the
17*4882a593Smuzhiyun  * GNU General Public License ("GPL") as published by the Free Software
18*4882a593Smuzhiyun  * Foundation, either version 2 of that License or (at your option) any
19*4882a593Smuzhiyun  * later version.
20*4882a593Smuzhiyun  *
21*4882a593Smuzhiyun  * THIS SOFTWARE IS PROVIDED BY NXP ``AS IS'' AND ANY
22*4882a593Smuzhiyun  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23*4882a593Smuzhiyun  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24*4882a593Smuzhiyun  * DISCLAIMED. IN NO EVENT SHALL NXP BE LIABLE FOR ANY
25*4882a593Smuzhiyun  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26*4882a593Smuzhiyun  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27*4882a593Smuzhiyun  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28*4882a593Smuzhiyun  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29*4882a593Smuzhiyun  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30*4882a593Smuzhiyun  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31*4882a593Smuzhiyun  */
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun #include <linux/slab.h>
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun #include "fman_keygen.h"
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun /* Maximum number of HW Ports */
40*4882a593Smuzhiyun #define FMAN_MAX_NUM_OF_HW_PORTS		64
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun /* Maximum number of KeyGen Schemes */
43*4882a593Smuzhiyun #define FM_KG_MAX_NUM_OF_SCHEMES		32
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun /* Number of generic KeyGen Generic Extract Command Registers */
46*4882a593Smuzhiyun #define FM_KG_NUM_OF_GENERIC_REGS		8
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun /* Dummy port ID */
49*4882a593Smuzhiyun #define DUMMY_PORT_ID				0
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun /* Select Scheme Value Register */
52*4882a593Smuzhiyun #define KG_SCH_DEF_USE_KGSE_DV_0		2
53*4882a593Smuzhiyun #define KG_SCH_DEF_USE_KGSE_DV_1		3
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun /* Registers Shifting values */
56*4882a593Smuzhiyun #define FM_KG_KGAR_NUM_SHIFT			16
57*4882a593Smuzhiyun #define KG_SCH_DEF_L4_PORT_SHIFT		8
58*4882a593Smuzhiyun #define KG_SCH_DEF_IP_ADDR_SHIFT		18
59*4882a593Smuzhiyun #define KG_SCH_HASH_CONFIG_SHIFT_SHIFT		24
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun /* KeyGen Registers bit field masks: */
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun /* Enable bit field mask for KeyGen General Configuration Register */
64*4882a593Smuzhiyun #define FM_KG_KGGCR_EN				0x80000000
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun /* KeyGen Global Registers bit field masks */
67*4882a593Smuzhiyun #define FM_KG_KGAR_GO				0x80000000
68*4882a593Smuzhiyun #define FM_KG_KGAR_READ				0x40000000
69*4882a593Smuzhiyun #define FM_KG_KGAR_WRITE			0x00000000
70*4882a593Smuzhiyun #define FM_KG_KGAR_SEL_SCHEME_ENTRY		0x00000000
71*4882a593Smuzhiyun #define FM_KG_KGAR_SCM_WSEL_UPDATE_CNT		0x00008000
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun #define FM_KG_KGAR_ERR				0x20000000
74*4882a593Smuzhiyun #define FM_KG_KGAR_SEL_CLS_PLAN_ENTRY		0x01000000
75*4882a593Smuzhiyun #define FM_KG_KGAR_SEL_PORT_ENTRY		0x02000000
76*4882a593Smuzhiyun #define FM_KG_KGAR_SEL_PORT_WSEL_SP		0x00008000
77*4882a593Smuzhiyun #define FM_KG_KGAR_SEL_PORT_WSEL_CPP		0x00004000
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun /* Error events exceptions */
80*4882a593Smuzhiyun #define FM_EX_KG_DOUBLE_ECC			0x80000000
81*4882a593Smuzhiyun #define FM_EX_KG_KEYSIZE_OVERFLOW		0x40000000
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun /* Scheme Registers bit field masks */
84*4882a593Smuzhiyun #define KG_SCH_MODE_EN				0x80000000
85*4882a593Smuzhiyun #define KG_SCH_VSP_NO_KSP_EN			0x80000000
86*4882a593Smuzhiyun #define KG_SCH_HASH_CONFIG_SYM			0x40000000
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun /* Known Protocol field codes */
89*4882a593Smuzhiyun #define KG_SCH_KN_PORT_ID		0x80000000
90*4882a593Smuzhiyun #define KG_SCH_KN_MACDST		0x40000000
91*4882a593Smuzhiyun #define KG_SCH_KN_MACSRC		0x20000000
92*4882a593Smuzhiyun #define KG_SCH_KN_TCI1			0x10000000
93*4882a593Smuzhiyun #define KG_SCH_KN_TCI2			0x08000000
94*4882a593Smuzhiyun #define KG_SCH_KN_ETYPE			0x04000000
95*4882a593Smuzhiyun #define KG_SCH_KN_PPPSID		0x02000000
96*4882a593Smuzhiyun #define KG_SCH_KN_PPPID			0x01000000
97*4882a593Smuzhiyun #define KG_SCH_KN_MPLS1			0x00800000
98*4882a593Smuzhiyun #define KG_SCH_KN_MPLS2			0x00400000
99*4882a593Smuzhiyun #define KG_SCH_KN_MPLS_LAST		0x00200000
100*4882a593Smuzhiyun #define KG_SCH_KN_IPSRC1		0x00100000
101*4882a593Smuzhiyun #define KG_SCH_KN_IPDST1		0x00080000
102*4882a593Smuzhiyun #define KG_SCH_KN_PTYPE1		0x00040000
103*4882a593Smuzhiyun #define KG_SCH_KN_IPTOS_TC1		0x00020000
104*4882a593Smuzhiyun #define KG_SCH_KN_IPV6FL1		0x00010000
105*4882a593Smuzhiyun #define KG_SCH_KN_IPSRC2		0x00008000
106*4882a593Smuzhiyun #define KG_SCH_KN_IPDST2		0x00004000
107*4882a593Smuzhiyun #define KG_SCH_KN_PTYPE2		0x00002000
108*4882a593Smuzhiyun #define KG_SCH_KN_IPTOS_TC2		0x00001000
109*4882a593Smuzhiyun #define KG_SCH_KN_IPV6FL2		0x00000800
110*4882a593Smuzhiyun #define KG_SCH_KN_GREPTYPE		0x00000400
111*4882a593Smuzhiyun #define KG_SCH_KN_IPSEC_SPI		0x00000200
112*4882a593Smuzhiyun #define KG_SCH_KN_IPSEC_NH		0x00000100
113*4882a593Smuzhiyun #define KG_SCH_KN_IPPID			0x00000080
114*4882a593Smuzhiyun #define KG_SCH_KN_L4PSRC		0x00000004
115*4882a593Smuzhiyun #define KG_SCH_KN_L4PDST		0x00000002
116*4882a593Smuzhiyun #define KG_SCH_KN_TFLG			0x00000001
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun /* NIA values */
119*4882a593Smuzhiyun #define NIA_ENG_BMI			0x00500000
120*4882a593Smuzhiyun #define NIA_BMI_AC_ENQ_FRAME		0x00000002
121*4882a593Smuzhiyun #define ENQUEUE_KG_DFLT_NIA		(NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME)
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun /* Hard-coded configuration:
124*4882a593Smuzhiyun  * These values are used as hard-coded values for KeyGen configuration
125*4882a593Smuzhiyun  * and they replace user selections for this hard-coded version
126*4882a593Smuzhiyun  */
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun /* Hash distribution shift */
129*4882a593Smuzhiyun #define DEFAULT_HASH_DIST_FQID_SHIFT		0
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun /* Hash shift */
132*4882a593Smuzhiyun #define DEFAULT_HASH_SHIFT			0
133*4882a593Smuzhiyun 
134*4882a593Smuzhiyun /* Symmetric hash usage:
135*4882a593Smuzhiyun  * Warning:
136*4882a593Smuzhiyun  * - the value for symmetric hash usage must be in accordance with hash
137*4882a593Smuzhiyun  *	key defined below
138*4882a593Smuzhiyun  * - according to tests performed, spreading is not working if symmetric
139*4882a593Smuzhiyun  *	hash is set on true
140*4882a593Smuzhiyun  * So ultimately symmetric hash functionality should be always disabled:
141*4882a593Smuzhiyun  */
142*4882a593Smuzhiyun #define DEFAULT_SYMMETRIC_HASH			false
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun /* Hash Key extraction fields: */
145*4882a593Smuzhiyun #define DEFAULT_HASH_KEY_EXTRACT_FIELDS		\
146*4882a593Smuzhiyun 	(KG_SCH_KN_IPSRC1 | KG_SCH_KN_IPDST1 | \
147*4882a593Smuzhiyun 	 KG_SCH_KN_L4PSRC | KG_SCH_KN_L4PDST | \
148*4882a593Smuzhiyun 	 KG_SCH_KN_IPSEC_SPI)
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun /* Default values to be used as hash key in case IPv4 or L4 (TCP, UDP)
151*4882a593Smuzhiyun  * don't exist in the frame
152*4882a593Smuzhiyun  */
153*4882a593Smuzhiyun /* Default IPv4 address */
154*4882a593Smuzhiyun #define DEFAULT_HASH_KEY_IPv4_ADDR		0x0A0A0A0A
155*4882a593Smuzhiyun /* Default L4 port */
156*4882a593Smuzhiyun #define DEFAULT_HASH_KEY_L4_PORT		0x0B0B0B0B
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun /* KeyGen Memory Mapped Registers: */
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun /* Scheme Configuration RAM Registers */
161*4882a593Smuzhiyun struct fman_kg_scheme_regs {
162*4882a593Smuzhiyun 	u32 kgse_mode;		/* 0x100: MODE */
163*4882a593Smuzhiyun 	u32 kgse_ekfc;		/* 0x104: Extract Known Fields Command */
164*4882a593Smuzhiyun 	u32 kgse_ekdv;		/* 0x108: Extract Known Default Value */
165*4882a593Smuzhiyun 	u32 kgse_bmch;		/* 0x10C: Bit Mask Command High */
166*4882a593Smuzhiyun 	u32 kgse_bmcl;		/* 0x110: Bit Mask Command Low */
167*4882a593Smuzhiyun 	u32 kgse_fqb;		/* 0x114: Frame Queue Base */
168*4882a593Smuzhiyun 	u32 kgse_hc;		/* 0x118: Hash Command */
169*4882a593Smuzhiyun 	u32 kgse_ppc;		/* 0x11C: Policer Profile Command */
170*4882a593Smuzhiyun 	u32 kgse_gec[FM_KG_NUM_OF_GENERIC_REGS];
171*4882a593Smuzhiyun 			/* 0x120: Generic Extract Command */
172*4882a593Smuzhiyun 	u32 kgse_spc;
173*4882a593Smuzhiyun 		/* 0x140: KeyGen Scheme Entry Statistic Packet Counter */
174*4882a593Smuzhiyun 	u32 kgse_dv0;	/* 0x144: KeyGen Scheme Entry Default Value 0 */
175*4882a593Smuzhiyun 	u32 kgse_dv1;	/* 0x148: KeyGen Scheme Entry Default Value 1 */
176*4882a593Smuzhiyun 	u32 kgse_ccbs;
177*4882a593Smuzhiyun 		/* 0x14C: KeyGen Scheme Entry Coarse Classification Bit*/
178*4882a593Smuzhiyun 	u32 kgse_mv;	/* 0x150: KeyGen Scheme Entry Match vector */
179*4882a593Smuzhiyun 	u32 kgse_om;	/* 0x154: KeyGen Scheme Entry Operation Mode bits */
180*4882a593Smuzhiyun 	u32 kgse_vsp;
181*4882a593Smuzhiyun 		/* 0x158: KeyGen Scheme Entry Virtual Storage Profile */
182*4882a593Smuzhiyun };
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun /* Port Partition Configuration Registers */
185*4882a593Smuzhiyun struct fman_kg_pe_regs {
186*4882a593Smuzhiyun 	u32 fmkg_pe_sp;		/* 0x100: KeyGen Port entry Scheme Partition */
187*4882a593Smuzhiyun 	u32 fmkg_pe_cpp;
188*4882a593Smuzhiyun 		/* 0x104: KeyGen Port Entry Classification Plan Partition */
189*4882a593Smuzhiyun };
190*4882a593Smuzhiyun 
191*4882a593Smuzhiyun /* General Configuration and Status Registers
192*4882a593Smuzhiyun  * Global Statistic Counters
193*4882a593Smuzhiyun  * KeyGen Global Registers
194*4882a593Smuzhiyun  */
195*4882a593Smuzhiyun struct fman_kg_regs {
196*4882a593Smuzhiyun 	u32 fmkg_gcr;	/* 0x000: KeyGen General Configuration Register */
197*4882a593Smuzhiyun 	u32 res004;	/* 0x004: Reserved */
198*4882a593Smuzhiyun 	u32 res008;	/* 0x008: Reserved */
199*4882a593Smuzhiyun 	u32 fmkg_eer;	/* 0x00C: KeyGen Error Event Register */
200*4882a593Smuzhiyun 	u32 fmkg_eeer;	/* 0x010: KeyGen Error Event Enable Register */
201*4882a593Smuzhiyun 	u32 res014;	/* 0x014: Reserved */
202*4882a593Smuzhiyun 	u32 res018;	/* 0x018: Reserved */
203*4882a593Smuzhiyun 	u32 fmkg_seer;	/* 0x01C: KeyGen Scheme Error Event Register */
204*4882a593Smuzhiyun 	u32 fmkg_seeer;	/* 0x020: KeyGen Scheme Error Event Enable Register */
205*4882a593Smuzhiyun 	u32 fmkg_gsr;	/* 0x024: KeyGen Global Status Register */
206*4882a593Smuzhiyun 	u32 fmkg_tpc;	/* 0x028: Total Packet Counter Register */
207*4882a593Smuzhiyun 	u32 fmkg_serc;	/* 0x02C: Soft Error Capture Register */
208*4882a593Smuzhiyun 	u32 res030[4];	/* 0x030: Reserved */
209*4882a593Smuzhiyun 	u32 fmkg_fdor;	/* 0x034: Frame Data Offset Register */
210*4882a593Smuzhiyun 	u32 fmkg_gdv0r;	/* 0x038: Global Default Value Register 0 */
211*4882a593Smuzhiyun 	u32 fmkg_gdv1r;	/* 0x03C: Global Default Value Register 1 */
212*4882a593Smuzhiyun 	u32 res04c[6];	/* 0x040: Reserved */
213*4882a593Smuzhiyun 	u32 fmkg_feer;	/* 0x044: Force Error Event Register */
214*4882a593Smuzhiyun 	u32 res068[38];	/* 0x048: Reserved */
215*4882a593Smuzhiyun 	union {
216*4882a593Smuzhiyun 		u32 fmkg_indirect[63];	/* 0x100: Indirect Access Registers */
217*4882a593Smuzhiyun 		struct fman_kg_scheme_regs fmkg_sch; /* Scheme Registers */
218*4882a593Smuzhiyun 		struct fman_kg_pe_regs fmkg_pe; /* Port Partition Registers */
219*4882a593Smuzhiyun 	};
220*4882a593Smuzhiyun 	u32 fmkg_ar;	/* 0x1FC: KeyGen Action Register */
221*4882a593Smuzhiyun };
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun /* KeyGen Scheme data */
224*4882a593Smuzhiyun struct keygen_scheme {
225*4882a593Smuzhiyun 	bool used;	/* Specifies if this scheme is used */
226*4882a593Smuzhiyun 	u8 hw_port_id;
227*4882a593Smuzhiyun 		/* Hardware port ID
228*4882a593Smuzhiyun 		 * schemes sharing between multiple ports is not
229*4882a593Smuzhiyun 		 * currently supported
230*4882a593Smuzhiyun 		 * so we have only one port id bound to a scheme
231*4882a593Smuzhiyun 		 */
232*4882a593Smuzhiyun 	u32 base_fqid;
233*4882a593Smuzhiyun 		/* Base FQID:
234*4882a593Smuzhiyun 		 * Must be between 1 and 2^24-1
235*4882a593Smuzhiyun 		 * If hash is used and an even distribution is
236*4882a593Smuzhiyun 		 * expected according to hash_fqid_count,
237*4882a593Smuzhiyun 		 * base_fqid must be aligned to hash_fqid_count
238*4882a593Smuzhiyun 		 */
239*4882a593Smuzhiyun 	u32 hash_fqid_count;
240*4882a593Smuzhiyun 		/* FQ range for hash distribution:
241*4882a593Smuzhiyun 		 * Must be a power of 2
242*4882a593Smuzhiyun 		 * Represents the range of queues for spreading
243*4882a593Smuzhiyun 		 */
244*4882a593Smuzhiyun 	bool use_hashing;	/* Usage of Hashing and spreading over FQ */
245*4882a593Smuzhiyun 	bool symmetric_hash;	/* Symmetric Hash option usage */
246*4882a593Smuzhiyun 	u8 hashShift;
247*4882a593Smuzhiyun 		/* Hash result right shift.
248*4882a593Smuzhiyun 		 * Select the 24 bits out of the 64 hash result.
249*4882a593Smuzhiyun 		 * 0 means using the 24 LSB's, otherwise
250*4882a593Smuzhiyun 		 * use the 24 LSB's after shifting right
251*4882a593Smuzhiyun 		 */
252*4882a593Smuzhiyun 	u32 match_vector;	/* Match Vector */
253*4882a593Smuzhiyun };
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun /* KeyGen driver data */
256*4882a593Smuzhiyun struct fman_keygen {
257*4882a593Smuzhiyun 	struct keygen_scheme schemes[FM_KG_MAX_NUM_OF_SCHEMES];
258*4882a593Smuzhiyun 				/* Array of schemes */
259*4882a593Smuzhiyun 	struct fman_kg_regs __iomem *keygen_regs;	/* KeyGen registers */
260*4882a593Smuzhiyun };
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun /* keygen_write_ar_wait
263*4882a593Smuzhiyun  *
264*4882a593Smuzhiyun  * Write Action Register with specified value, wait for GO bit field to be
265*4882a593Smuzhiyun  * idle and then read the error
266*4882a593Smuzhiyun  *
267*4882a593Smuzhiyun  * regs: KeyGen registers
268*4882a593Smuzhiyun  * fmkg_ar: Action Register value
269*4882a593Smuzhiyun  *
270*4882a593Smuzhiyun  * Return: Zero for success or error code in case of failure
271*4882a593Smuzhiyun  */
keygen_write_ar_wait(struct fman_kg_regs __iomem * regs,u32 fmkg_ar)272*4882a593Smuzhiyun static int keygen_write_ar_wait(struct fman_kg_regs __iomem *regs, u32 fmkg_ar)
273*4882a593Smuzhiyun {
274*4882a593Smuzhiyun 	iowrite32be(fmkg_ar, &regs->fmkg_ar);
275*4882a593Smuzhiyun 
276*4882a593Smuzhiyun 	/* Wait for GO bit field to be idle */
277*4882a593Smuzhiyun 	while (fmkg_ar & FM_KG_KGAR_GO)
278*4882a593Smuzhiyun 		fmkg_ar = ioread32be(&regs->fmkg_ar);
279*4882a593Smuzhiyun 
280*4882a593Smuzhiyun 	if (fmkg_ar & FM_KG_KGAR_ERR)
281*4882a593Smuzhiyun 		return -EINVAL;
282*4882a593Smuzhiyun 
283*4882a593Smuzhiyun 	return 0;
284*4882a593Smuzhiyun }
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun /* build_ar_scheme
287*4882a593Smuzhiyun  *
288*4882a593Smuzhiyun  * Build Action Register value for scheme settings
289*4882a593Smuzhiyun  *
290*4882a593Smuzhiyun  * scheme_id: Scheme ID
291*4882a593Smuzhiyun  * update_counter: update scheme counter
292*4882a593Smuzhiyun  * write: true for action to write the scheme or false for read action
293*4882a593Smuzhiyun  *
294*4882a593Smuzhiyun  * Return: AR value
295*4882a593Smuzhiyun  */
build_ar_scheme(u8 scheme_id,bool update_counter,bool write)296*4882a593Smuzhiyun static u32 build_ar_scheme(u8 scheme_id, bool update_counter, bool write)
297*4882a593Smuzhiyun {
298*4882a593Smuzhiyun 	u32 rw = (u32)(write ? FM_KG_KGAR_WRITE : FM_KG_KGAR_READ);
299*4882a593Smuzhiyun 
300*4882a593Smuzhiyun 	return (u32)(FM_KG_KGAR_GO |
301*4882a593Smuzhiyun 			rw |
302*4882a593Smuzhiyun 			FM_KG_KGAR_SEL_SCHEME_ENTRY |
303*4882a593Smuzhiyun 			DUMMY_PORT_ID |
304*4882a593Smuzhiyun 			((u32)scheme_id << FM_KG_KGAR_NUM_SHIFT) |
305*4882a593Smuzhiyun 			(update_counter ? FM_KG_KGAR_SCM_WSEL_UPDATE_CNT : 0));
306*4882a593Smuzhiyun }
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun /* build_ar_bind_scheme
309*4882a593Smuzhiyun  *
310*4882a593Smuzhiyun  * Build Action Register value for port binding to schemes
311*4882a593Smuzhiyun  *
312*4882a593Smuzhiyun  * hwport_id: HW Port ID
313*4882a593Smuzhiyun  * write: true for action to write the bind or false for read action
314*4882a593Smuzhiyun  *
315*4882a593Smuzhiyun  * Return: AR value
316*4882a593Smuzhiyun  */
build_ar_bind_scheme(u8 hwport_id,bool write)317*4882a593Smuzhiyun static u32 build_ar_bind_scheme(u8 hwport_id, bool write)
318*4882a593Smuzhiyun {
319*4882a593Smuzhiyun 	u32 rw = write ? (u32)FM_KG_KGAR_WRITE : (u32)FM_KG_KGAR_READ;
320*4882a593Smuzhiyun 
321*4882a593Smuzhiyun 	return (u32)(FM_KG_KGAR_GO |
322*4882a593Smuzhiyun 			rw |
323*4882a593Smuzhiyun 			FM_KG_KGAR_SEL_PORT_ENTRY |
324*4882a593Smuzhiyun 			hwport_id |
325*4882a593Smuzhiyun 			FM_KG_KGAR_SEL_PORT_WSEL_SP);
326*4882a593Smuzhiyun }
327*4882a593Smuzhiyun 
328*4882a593Smuzhiyun /* keygen_write_sp
329*4882a593Smuzhiyun  *
330*4882a593Smuzhiyun  * Write Scheme Partition Register with specified value
331*4882a593Smuzhiyun  *
332*4882a593Smuzhiyun  * regs: KeyGen Registers
333*4882a593Smuzhiyun  * sp: Scheme Partition register value
334*4882a593Smuzhiyun  * add: true to add a scheme partition or false to clear
335*4882a593Smuzhiyun  *
336*4882a593Smuzhiyun  * Return: none
337*4882a593Smuzhiyun  */
keygen_write_sp(struct fman_kg_regs __iomem * regs,u32 sp,bool add)338*4882a593Smuzhiyun static void keygen_write_sp(struct fman_kg_regs __iomem *regs, u32 sp, bool add)
339*4882a593Smuzhiyun {
340*4882a593Smuzhiyun 	u32 tmp;
341*4882a593Smuzhiyun 
342*4882a593Smuzhiyun 	tmp = ioread32be(&regs->fmkg_pe.fmkg_pe_sp);
343*4882a593Smuzhiyun 
344*4882a593Smuzhiyun 	if (add)
345*4882a593Smuzhiyun 		tmp |= sp;
346*4882a593Smuzhiyun 	else
347*4882a593Smuzhiyun 		tmp &= ~sp;
348*4882a593Smuzhiyun 
349*4882a593Smuzhiyun 	iowrite32be(tmp, &regs->fmkg_pe.fmkg_pe_sp);
350*4882a593Smuzhiyun }
351*4882a593Smuzhiyun 
352*4882a593Smuzhiyun /* build_ar_bind_cls_plan
353*4882a593Smuzhiyun  *
354*4882a593Smuzhiyun  * Build Action Register value for Classification Plan
355*4882a593Smuzhiyun  *
356*4882a593Smuzhiyun  * hwport_id: HW Port ID
357*4882a593Smuzhiyun  * write: true for action to write the CP or false for read action
358*4882a593Smuzhiyun  *
359*4882a593Smuzhiyun  * Return: AR value
360*4882a593Smuzhiyun  */
build_ar_bind_cls_plan(u8 hwport_id,bool write)361*4882a593Smuzhiyun static u32 build_ar_bind_cls_plan(u8 hwport_id, bool write)
362*4882a593Smuzhiyun {
363*4882a593Smuzhiyun 	u32 rw = write ? (u32)FM_KG_KGAR_WRITE : (u32)FM_KG_KGAR_READ;
364*4882a593Smuzhiyun 
365*4882a593Smuzhiyun 	return (u32)(FM_KG_KGAR_GO |
366*4882a593Smuzhiyun 			rw |
367*4882a593Smuzhiyun 			FM_KG_KGAR_SEL_PORT_ENTRY |
368*4882a593Smuzhiyun 			hwport_id |
369*4882a593Smuzhiyun 			FM_KG_KGAR_SEL_PORT_WSEL_CPP);
370*4882a593Smuzhiyun }
371*4882a593Smuzhiyun 
372*4882a593Smuzhiyun /* keygen_write_cpp
373*4882a593Smuzhiyun  *
374*4882a593Smuzhiyun  * Write Classification Plan Partition Register with specified value
375*4882a593Smuzhiyun  *
376*4882a593Smuzhiyun  * regs: KeyGen Registers
377*4882a593Smuzhiyun  * cpp: CPP register value
378*4882a593Smuzhiyun  *
379*4882a593Smuzhiyun  * Return: none
380*4882a593Smuzhiyun  */
keygen_write_cpp(struct fman_kg_regs __iomem * regs,u32 cpp)381*4882a593Smuzhiyun static void keygen_write_cpp(struct fman_kg_regs __iomem *regs, u32 cpp)
382*4882a593Smuzhiyun {
383*4882a593Smuzhiyun 	iowrite32be(cpp, &regs->fmkg_pe.fmkg_pe_cpp);
384*4882a593Smuzhiyun }
385*4882a593Smuzhiyun 
386*4882a593Smuzhiyun /* keygen_write_scheme
387*4882a593Smuzhiyun  *
388*4882a593Smuzhiyun  * Write all Schemes Registers with specified values
389*4882a593Smuzhiyun  *
390*4882a593Smuzhiyun  * regs: KeyGen Registers
391*4882a593Smuzhiyun  * scheme_id: Scheme ID
392*4882a593Smuzhiyun  * scheme_regs: Scheme registers values desired to be written
393*4882a593Smuzhiyun  * update_counter: update scheme counter
394*4882a593Smuzhiyun  *
395*4882a593Smuzhiyun  * Return: Zero for success or error code in case of failure
396*4882a593Smuzhiyun  */
keygen_write_scheme(struct fman_kg_regs __iomem * regs,u8 scheme_id,struct fman_kg_scheme_regs * scheme_regs,bool update_counter)397*4882a593Smuzhiyun static int keygen_write_scheme(struct fman_kg_regs __iomem *regs, u8 scheme_id,
398*4882a593Smuzhiyun 			       struct fman_kg_scheme_regs *scheme_regs,
399*4882a593Smuzhiyun 				bool update_counter)
400*4882a593Smuzhiyun {
401*4882a593Smuzhiyun 	u32 ar_reg;
402*4882a593Smuzhiyun 	int err, i;
403*4882a593Smuzhiyun 
404*4882a593Smuzhiyun 	/* Write indirect scheme registers */
405*4882a593Smuzhiyun 	iowrite32be(scheme_regs->kgse_mode, &regs->fmkg_sch.kgse_mode);
406*4882a593Smuzhiyun 	iowrite32be(scheme_regs->kgse_ekfc, &regs->fmkg_sch.kgse_ekfc);
407*4882a593Smuzhiyun 	iowrite32be(scheme_regs->kgse_ekdv, &regs->fmkg_sch.kgse_ekdv);
408*4882a593Smuzhiyun 	iowrite32be(scheme_regs->kgse_bmch, &regs->fmkg_sch.kgse_bmch);
409*4882a593Smuzhiyun 	iowrite32be(scheme_regs->kgse_bmcl, &regs->fmkg_sch.kgse_bmcl);
410*4882a593Smuzhiyun 	iowrite32be(scheme_regs->kgse_fqb, &regs->fmkg_sch.kgse_fqb);
411*4882a593Smuzhiyun 	iowrite32be(scheme_regs->kgse_hc, &regs->fmkg_sch.kgse_hc);
412*4882a593Smuzhiyun 	iowrite32be(scheme_regs->kgse_ppc, &regs->fmkg_sch.kgse_ppc);
413*4882a593Smuzhiyun 	iowrite32be(scheme_regs->kgse_spc, &regs->fmkg_sch.kgse_spc);
414*4882a593Smuzhiyun 	iowrite32be(scheme_regs->kgse_dv0, &regs->fmkg_sch.kgse_dv0);
415*4882a593Smuzhiyun 	iowrite32be(scheme_regs->kgse_dv1, &regs->fmkg_sch.kgse_dv1);
416*4882a593Smuzhiyun 	iowrite32be(scheme_regs->kgse_ccbs, &regs->fmkg_sch.kgse_ccbs);
417*4882a593Smuzhiyun 	iowrite32be(scheme_regs->kgse_mv, &regs->fmkg_sch.kgse_mv);
418*4882a593Smuzhiyun 	iowrite32be(scheme_regs->kgse_om, &regs->fmkg_sch.kgse_om);
419*4882a593Smuzhiyun 	iowrite32be(scheme_regs->kgse_vsp, &regs->fmkg_sch.kgse_vsp);
420*4882a593Smuzhiyun 
421*4882a593Smuzhiyun 	for (i = 0 ; i < FM_KG_NUM_OF_GENERIC_REGS ; i++)
422*4882a593Smuzhiyun 		iowrite32be(scheme_regs->kgse_gec[i],
423*4882a593Smuzhiyun 			    &regs->fmkg_sch.kgse_gec[i]);
424*4882a593Smuzhiyun 
425*4882a593Smuzhiyun 	/* Write AR (Action register) */
426*4882a593Smuzhiyun 	ar_reg = build_ar_scheme(scheme_id, update_counter, true);
427*4882a593Smuzhiyun 	err = keygen_write_ar_wait(regs, ar_reg);
428*4882a593Smuzhiyun 	if (err != 0) {
429*4882a593Smuzhiyun 		pr_err("Writing Action Register failed\n");
430*4882a593Smuzhiyun 		return err;
431*4882a593Smuzhiyun 	}
432*4882a593Smuzhiyun 
433*4882a593Smuzhiyun 	return err;
434*4882a593Smuzhiyun }
435*4882a593Smuzhiyun 
436*4882a593Smuzhiyun /* get_free_scheme_id
437*4882a593Smuzhiyun  *
438*4882a593Smuzhiyun  * Find the first free scheme available to be used
439*4882a593Smuzhiyun  *
440*4882a593Smuzhiyun  * keygen: KeyGen handle
441*4882a593Smuzhiyun  * scheme_id: pointer to scheme id
442*4882a593Smuzhiyun  *
443*4882a593Smuzhiyun  * Return: 0 on success, -EINVAL when the are no available free schemes
444*4882a593Smuzhiyun  */
get_free_scheme_id(struct fman_keygen * keygen,u8 * scheme_id)445*4882a593Smuzhiyun static int get_free_scheme_id(struct fman_keygen *keygen, u8 *scheme_id)
446*4882a593Smuzhiyun {
447*4882a593Smuzhiyun 	u8 i;
448*4882a593Smuzhiyun 
449*4882a593Smuzhiyun 	for (i = 0; i < FM_KG_MAX_NUM_OF_SCHEMES; i++)
450*4882a593Smuzhiyun 		if (!keygen->schemes[i].used) {
451*4882a593Smuzhiyun 			*scheme_id = i;
452*4882a593Smuzhiyun 			return 0;
453*4882a593Smuzhiyun 		}
454*4882a593Smuzhiyun 
455*4882a593Smuzhiyun 	return -EINVAL;
456*4882a593Smuzhiyun }
457*4882a593Smuzhiyun 
458*4882a593Smuzhiyun /* get_scheme
459*4882a593Smuzhiyun  *
460*4882a593Smuzhiyun  * Provides the scheme for specified ID
461*4882a593Smuzhiyun  *
462*4882a593Smuzhiyun  * keygen: KeyGen handle
463*4882a593Smuzhiyun  * scheme_id: Scheme ID
464*4882a593Smuzhiyun  *
465*4882a593Smuzhiyun  * Return: handle to required scheme
466*4882a593Smuzhiyun  */
get_scheme(struct fman_keygen * keygen,u8 scheme_id)467*4882a593Smuzhiyun static struct keygen_scheme *get_scheme(struct fman_keygen *keygen,
468*4882a593Smuzhiyun 					u8 scheme_id)
469*4882a593Smuzhiyun {
470*4882a593Smuzhiyun 	if (scheme_id >= FM_KG_MAX_NUM_OF_SCHEMES)
471*4882a593Smuzhiyun 		return NULL;
472*4882a593Smuzhiyun 	return &keygen->schemes[scheme_id];
473*4882a593Smuzhiyun }
474*4882a593Smuzhiyun 
475*4882a593Smuzhiyun /* keygen_bind_port_to_schemes
476*4882a593Smuzhiyun  *
477*4882a593Smuzhiyun  * Bind the port to schemes
478*4882a593Smuzhiyun  *
479*4882a593Smuzhiyun  * keygen: KeyGen handle
480*4882a593Smuzhiyun  * scheme_id: id of the scheme to bind to
481*4882a593Smuzhiyun  * bind: true to bind the port or false to unbind it
482*4882a593Smuzhiyun  *
483*4882a593Smuzhiyun  * Return: Zero for success or error code in case of failure
484*4882a593Smuzhiyun  */
keygen_bind_port_to_schemes(struct fman_keygen * keygen,u8 scheme_id,bool bind)485*4882a593Smuzhiyun static int keygen_bind_port_to_schemes(struct fman_keygen *keygen,
486*4882a593Smuzhiyun 				       u8 scheme_id,
487*4882a593Smuzhiyun 					bool bind)
488*4882a593Smuzhiyun {
489*4882a593Smuzhiyun 	struct fman_kg_regs __iomem *keygen_regs = keygen->keygen_regs;
490*4882a593Smuzhiyun 	struct keygen_scheme *scheme;
491*4882a593Smuzhiyun 	u32 ar_reg;
492*4882a593Smuzhiyun 	u32 schemes_vector = 0;
493*4882a593Smuzhiyun 	int err;
494*4882a593Smuzhiyun 
495*4882a593Smuzhiyun 	scheme = get_scheme(keygen, scheme_id);
496*4882a593Smuzhiyun 	if (!scheme) {
497*4882a593Smuzhiyun 		pr_err("Requested Scheme does not exist\n");
498*4882a593Smuzhiyun 		return -EINVAL;
499*4882a593Smuzhiyun 	}
500*4882a593Smuzhiyun 	if (!scheme->used) {
501*4882a593Smuzhiyun 		pr_err("Cannot bind port to an invalid scheme\n");
502*4882a593Smuzhiyun 		return -EINVAL;
503*4882a593Smuzhiyun 	}
504*4882a593Smuzhiyun 
505*4882a593Smuzhiyun 	schemes_vector |= 1 << (31 - scheme_id);
506*4882a593Smuzhiyun 
507*4882a593Smuzhiyun 	ar_reg = build_ar_bind_scheme(scheme->hw_port_id, false);
508*4882a593Smuzhiyun 	err = keygen_write_ar_wait(keygen_regs, ar_reg);
509*4882a593Smuzhiyun 	if (err != 0) {
510*4882a593Smuzhiyun 		pr_err("Reading Action Register failed\n");
511*4882a593Smuzhiyun 		return err;
512*4882a593Smuzhiyun 	}
513*4882a593Smuzhiyun 
514*4882a593Smuzhiyun 	keygen_write_sp(keygen_regs, schemes_vector, bind);
515*4882a593Smuzhiyun 
516*4882a593Smuzhiyun 	ar_reg = build_ar_bind_scheme(scheme->hw_port_id, true);
517*4882a593Smuzhiyun 	err = keygen_write_ar_wait(keygen_regs, ar_reg);
518*4882a593Smuzhiyun 	if (err != 0) {
519*4882a593Smuzhiyun 		pr_err("Writing Action Register failed\n");
520*4882a593Smuzhiyun 		return err;
521*4882a593Smuzhiyun 	}
522*4882a593Smuzhiyun 
523*4882a593Smuzhiyun 	return 0;
524*4882a593Smuzhiyun }
525*4882a593Smuzhiyun 
526*4882a593Smuzhiyun /* keygen_scheme_setup
527*4882a593Smuzhiyun  *
528*4882a593Smuzhiyun  * Setup the scheme according to required configuration
529*4882a593Smuzhiyun  *
530*4882a593Smuzhiyun  * keygen: KeyGen handle
531*4882a593Smuzhiyun  * scheme_id: scheme ID
532*4882a593Smuzhiyun  * enable: true to enable scheme or false to disable it
533*4882a593Smuzhiyun  *
534*4882a593Smuzhiyun  * Return: Zero for success or error code in case of failure
535*4882a593Smuzhiyun  */
keygen_scheme_setup(struct fman_keygen * keygen,u8 scheme_id,bool enable)536*4882a593Smuzhiyun static int keygen_scheme_setup(struct fman_keygen *keygen, u8 scheme_id,
537*4882a593Smuzhiyun 			       bool enable)
538*4882a593Smuzhiyun {
539*4882a593Smuzhiyun 	struct fman_kg_regs __iomem *keygen_regs = keygen->keygen_regs;
540*4882a593Smuzhiyun 	struct fman_kg_scheme_regs scheme_regs;
541*4882a593Smuzhiyun 	struct keygen_scheme *scheme;
542*4882a593Smuzhiyun 	u32 tmp_reg;
543*4882a593Smuzhiyun 	int err;
544*4882a593Smuzhiyun 
545*4882a593Smuzhiyun 	scheme = get_scheme(keygen, scheme_id);
546*4882a593Smuzhiyun 	if (!scheme) {
547*4882a593Smuzhiyun 		pr_err("Requested Scheme does not exist\n");
548*4882a593Smuzhiyun 		return -EINVAL;
549*4882a593Smuzhiyun 	}
550*4882a593Smuzhiyun 	if (enable && scheme->used) {
551*4882a593Smuzhiyun 		pr_err("The requested Scheme is already used\n");
552*4882a593Smuzhiyun 		return -EINVAL;
553*4882a593Smuzhiyun 	}
554*4882a593Smuzhiyun 
555*4882a593Smuzhiyun 	/* Clear scheme registers */
556*4882a593Smuzhiyun 	memset(&scheme_regs, 0, sizeof(struct fman_kg_scheme_regs));
557*4882a593Smuzhiyun 
558*4882a593Smuzhiyun 	/* Setup all scheme registers: */
559*4882a593Smuzhiyun 	tmp_reg = 0;
560*4882a593Smuzhiyun 
561*4882a593Smuzhiyun 	if (enable) {
562*4882a593Smuzhiyun 		/* Enable Scheme */
563*4882a593Smuzhiyun 		tmp_reg |= KG_SCH_MODE_EN;
564*4882a593Smuzhiyun 		/* Enqueue frame NIA */
565*4882a593Smuzhiyun 		tmp_reg |= ENQUEUE_KG_DFLT_NIA;
566*4882a593Smuzhiyun 	}
567*4882a593Smuzhiyun 
568*4882a593Smuzhiyun 	scheme_regs.kgse_mode = tmp_reg;
569*4882a593Smuzhiyun 
570*4882a593Smuzhiyun 	scheme_regs.kgse_mv = scheme->match_vector;
571*4882a593Smuzhiyun 
572*4882a593Smuzhiyun 	/* Scheme don't override StorageProfile:
573*4882a593Smuzhiyun 	 * valid only for DPAA_VERSION >= 11
574*4882a593Smuzhiyun 	 */
575*4882a593Smuzhiyun 	scheme_regs.kgse_vsp = KG_SCH_VSP_NO_KSP_EN;
576*4882a593Smuzhiyun 
577*4882a593Smuzhiyun 	/* Configure Hard-Coded Rx Hashing: */
578*4882a593Smuzhiyun 
579*4882a593Smuzhiyun 	if (scheme->use_hashing) {
580*4882a593Smuzhiyun 		/* configure kgse_ekfc */
581*4882a593Smuzhiyun 		scheme_regs.kgse_ekfc = DEFAULT_HASH_KEY_EXTRACT_FIELDS;
582*4882a593Smuzhiyun 
583*4882a593Smuzhiyun 		/* configure kgse_ekdv */
584*4882a593Smuzhiyun 		tmp_reg = 0;
585*4882a593Smuzhiyun 		tmp_reg |= (KG_SCH_DEF_USE_KGSE_DV_0 <<
586*4882a593Smuzhiyun 				KG_SCH_DEF_IP_ADDR_SHIFT);
587*4882a593Smuzhiyun 		tmp_reg |= (KG_SCH_DEF_USE_KGSE_DV_1 <<
588*4882a593Smuzhiyun 				KG_SCH_DEF_L4_PORT_SHIFT);
589*4882a593Smuzhiyun 		scheme_regs.kgse_ekdv = tmp_reg;
590*4882a593Smuzhiyun 
591*4882a593Smuzhiyun 		/* configure kgse_dv0 */
592*4882a593Smuzhiyun 		scheme_regs.kgse_dv0 = DEFAULT_HASH_KEY_IPv4_ADDR;
593*4882a593Smuzhiyun 		/* configure kgse_dv1 */
594*4882a593Smuzhiyun 		scheme_regs.kgse_dv1 = DEFAULT_HASH_KEY_L4_PORT;
595*4882a593Smuzhiyun 
596*4882a593Smuzhiyun 		/* configure kgse_hc  */
597*4882a593Smuzhiyun 		tmp_reg = 0;
598*4882a593Smuzhiyun 		tmp_reg |= ((scheme->hash_fqid_count - 1) <<
599*4882a593Smuzhiyun 				DEFAULT_HASH_DIST_FQID_SHIFT);
600*4882a593Smuzhiyun 		tmp_reg |= scheme->hashShift << KG_SCH_HASH_CONFIG_SHIFT_SHIFT;
601*4882a593Smuzhiyun 
602*4882a593Smuzhiyun 		if (scheme->symmetric_hash) {
603*4882a593Smuzhiyun 			/* Normally extraction key should be verified if
604*4882a593Smuzhiyun 			 * complies with symmetric hash
605*4882a593Smuzhiyun 			 * But because extraction is hard-coded, we are sure
606*4882a593Smuzhiyun 			 * the key is symmetric
607*4882a593Smuzhiyun 			 */
608*4882a593Smuzhiyun 			tmp_reg |= KG_SCH_HASH_CONFIG_SYM;
609*4882a593Smuzhiyun 		}
610*4882a593Smuzhiyun 		scheme_regs.kgse_hc = tmp_reg;
611*4882a593Smuzhiyun 	} else {
612*4882a593Smuzhiyun 		scheme_regs.kgse_ekfc = 0;
613*4882a593Smuzhiyun 		scheme_regs.kgse_hc = 0;
614*4882a593Smuzhiyun 		scheme_regs.kgse_ekdv = 0;
615*4882a593Smuzhiyun 		scheme_regs.kgse_dv0 = 0;
616*4882a593Smuzhiyun 		scheme_regs.kgse_dv1 = 0;
617*4882a593Smuzhiyun 	}
618*4882a593Smuzhiyun 
619*4882a593Smuzhiyun 	/* configure kgse_fqb: Scheme FQID base */
620*4882a593Smuzhiyun 	tmp_reg = 0;
621*4882a593Smuzhiyun 	tmp_reg |= scheme->base_fqid;
622*4882a593Smuzhiyun 	scheme_regs.kgse_fqb = tmp_reg;
623*4882a593Smuzhiyun 
624*4882a593Smuzhiyun 	/* features not used by hard-coded configuration */
625*4882a593Smuzhiyun 	scheme_regs.kgse_bmch = 0;
626*4882a593Smuzhiyun 	scheme_regs.kgse_bmcl = 0;
627*4882a593Smuzhiyun 	scheme_regs.kgse_spc = 0;
628*4882a593Smuzhiyun 
629*4882a593Smuzhiyun 	/* Write scheme registers */
630*4882a593Smuzhiyun 	err = keygen_write_scheme(keygen_regs, scheme_id, &scheme_regs, true);
631*4882a593Smuzhiyun 	if (err != 0) {
632*4882a593Smuzhiyun 		pr_err("Writing scheme registers failed\n");
633*4882a593Smuzhiyun 		return err;
634*4882a593Smuzhiyun 	}
635*4882a593Smuzhiyun 
636*4882a593Smuzhiyun 	/* Update used field for Scheme */
637*4882a593Smuzhiyun 	scheme->used = enable;
638*4882a593Smuzhiyun 
639*4882a593Smuzhiyun 	return 0;
640*4882a593Smuzhiyun }
641*4882a593Smuzhiyun 
642*4882a593Smuzhiyun /* keygen_init
643*4882a593Smuzhiyun  *
644*4882a593Smuzhiyun  * KeyGen initialization:
645*4882a593Smuzhiyun  * Initializes and enables KeyGen, allocate driver memory, setup registers,
646*4882a593Smuzhiyun  * clear port bindings, invalidate all schemes
647*4882a593Smuzhiyun  *
648*4882a593Smuzhiyun  * keygen_regs: KeyGen registers base address
649*4882a593Smuzhiyun  *
650*4882a593Smuzhiyun  * Return: Handle to KeyGen driver
651*4882a593Smuzhiyun  */
keygen_init(struct fman_kg_regs __iomem * keygen_regs)652*4882a593Smuzhiyun struct fman_keygen *keygen_init(struct fman_kg_regs __iomem *keygen_regs)
653*4882a593Smuzhiyun {
654*4882a593Smuzhiyun 	struct fman_keygen *keygen;
655*4882a593Smuzhiyun 	u32 ar;
656*4882a593Smuzhiyun 	int i;
657*4882a593Smuzhiyun 
658*4882a593Smuzhiyun 	/* Allocate memory for KeyGen driver */
659*4882a593Smuzhiyun 	keygen = kzalloc(sizeof(*keygen), GFP_KERNEL);
660*4882a593Smuzhiyun 	if (!keygen)
661*4882a593Smuzhiyun 		return NULL;
662*4882a593Smuzhiyun 
663*4882a593Smuzhiyun 	keygen->keygen_regs = keygen_regs;
664*4882a593Smuzhiyun 
665*4882a593Smuzhiyun 	/* KeyGen initialization (for Master partition):
666*4882a593Smuzhiyun 	 * Setup KeyGen registers
667*4882a593Smuzhiyun 	 */
668*4882a593Smuzhiyun 	iowrite32be(ENQUEUE_KG_DFLT_NIA, &keygen_regs->fmkg_gcr);
669*4882a593Smuzhiyun 
670*4882a593Smuzhiyun 	iowrite32be(FM_EX_KG_DOUBLE_ECC | FM_EX_KG_KEYSIZE_OVERFLOW,
671*4882a593Smuzhiyun 		    &keygen_regs->fmkg_eer);
672*4882a593Smuzhiyun 
673*4882a593Smuzhiyun 	iowrite32be(0, &keygen_regs->fmkg_fdor);
674*4882a593Smuzhiyun 	iowrite32be(0, &keygen_regs->fmkg_gdv0r);
675*4882a593Smuzhiyun 	iowrite32be(0, &keygen_regs->fmkg_gdv1r);
676*4882a593Smuzhiyun 
677*4882a593Smuzhiyun 	/* Clear binding between ports to schemes and classification plans
678*4882a593Smuzhiyun 	 * so that all ports are not bound to any scheme/classification plan
679*4882a593Smuzhiyun 	 */
680*4882a593Smuzhiyun 	for (i = 0; i < FMAN_MAX_NUM_OF_HW_PORTS; i++) {
681*4882a593Smuzhiyun 		/* Clear all pe sp schemes registers */
682*4882a593Smuzhiyun 		keygen_write_sp(keygen_regs, 0xffffffff, false);
683*4882a593Smuzhiyun 		ar = build_ar_bind_scheme(i, true);
684*4882a593Smuzhiyun 		keygen_write_ar_wait(keygen_regs, ar);
685*4882a593Smuzhiyun 
686*4882a593Smuzhiyun 		/* Clear all pe cpp classification plans registers */
687*4882a593Smuzhiyun 		keygen_write_cpp(keygen_regs, 0);
688*4882a593Smuzhiyun 		ar = build_ar_bind_cls_plan(i, true);
689*4882a593Smuzhiyun 		keygen_write_ar_wait(keygen_regs, ar);
690*4882a593Smuzhiyun 	}
691*4882a593Smuzhiyun 
692*4882a593Smuzhiyun 	/* Enable all scheme interrupts */
693*4882a593Smuzhiyun 	iowrite32be(0xFFFFFFFF, &keygen_regs->fmkg_seer);
694*4882a593Smuzhiyun 	iowrite32be(0xFFFFFFFF, &keygen_regs->fmkg_seeer);
695*4882a593Smuzhiyun 
696*4882a593Smuzhiyun 	/* Enable KyeGen */
697*4882a593Smuzhiyun 	iowrite32be(ioread32be(&keygen_regs->fmkg_gcr) | FM_KG_KGGCR_EN,
698*4882a593Smuzhiyun 		    &keygen_regs->fmkg_gcr);
699*4882a593Smuzhiyun 
700*4882a593Smuzhiyun 	return keygen;
701*4882a593Smuzhiyun }
702*4882a593Smuzhiyun EXPORT_SYMBOL(keygen_init);
703*4882a593Smuzhiyun 
704*4882a593Smuzhiyun /* keygen_port_hashing_init
705*4882a593Smuzhiyun  *
706*4882a593Smuzhiyun  * Initializes a port for Rx Hashing with specified configuration parameters
707*4882a593Smuzhiyun  *
708*4882a593Smuzhiyun  * keygen: KeyGen handle
709*4882a593Smuzhiyun  * hw_port_id: HW Port ID
710*4882a593Smuzhiyun  * hash_base_fqid: Hashing Base FQID used for spreading
711*4882a593Smuzhiyun  * hash_size: Hashing size
712*4882a593Smuzhiyun  *
713*4882a593Smuzhiyun  * Return: Zero for success or error code in case of failure
714*4882a593Smuzhiyun  */
keygen_port_hashing_init(struct fman_keygen * keygen,u8 hw_port_id,u32 hash_base_fqid,u32 hash_size)715*4882a593Smuzhiyun int keygen_port_hashing_init(struct fman_keygen *keygen, u8 hw_port_id,
716*4882a593Smuzhiyun 			     u32 hash_base_fqid, u32 hash_size)
717*4882a593Smuzhiyun {
718*4882a593Smuzhiyun 	struct keygen_scheme *scheme;
719*4882a593Smuzhiyun 	u8 scheme_id;
720*4882a593Smuzhiyun 	int err;
721*4882a593Smuzhiyun 
722*4882a593Smuzhiyun 	/* Validate Scheme configuration parameters */
723*4882a593Smuzhiyun 	if (hash_base_fqid == 0 || (hash_base_fqid & ~0x00FFFFFF)) {
724*4882a593Smuzhiyun 		pr_err("Base FQID must be between 1 and 2^24-1\n");
725*4882a593Smuzhiyun 		return -EINVAL;
726*4882a593Smuzhiyun 	}
727*4882a593Smuzhiyun 	if (hash_size == 0 || (hash_size & (hash_size - 1)) != 0) {
728*4882a593Smuzhiyun 		pr_err("Hash size must be power of two\n");
729*4882a593Smuzhiyun 		return -EINVAL;
730*4882a593Smuzhiyun 	}
731*4882a593Smuzhiyun 
732*4882a593Smuzhiyun 	/* Find a free scheme */
733*4882a593Smuzhiyun 	err = get_free_scheme_id(keygen, &scheme_id);
734*4882a593Smuzhiyun 	if (err) {
735*4882a593Smuzhiyun 		pr_err("The maximum number of available Schemes has been exceeded\n");
736*4882a593Smuzhiyun 		return -EINVAL;
737*4882a593Smuzhiyun 	}
738*4882a593Smuzhiyun 
739*4882a593Smuzhiyun 	/* Create and configure Hard-Coded Scheme: */
740*4882a593Smuzhiyun 
741*4882a593Smuzhiyun 	scheme = get_scheme(keygen, scheme_id);
742*4882a593Smuzhiyun 	if (!scheme) {
743*4882a593Smuzhiyun 		pr_err("Requested Scheme does not exist\n");
744*4882a593Smuzhiyun 		return -EINVAL;
745*4882a593Smuzhiyun 	}
746*4882a593Smuzhiyun 	if (scheme->used) {
747*4882a593Smuzhiyun 		pr_err("The requested Scheme is already used\n");
748*4882a593Smuzhiyun 		return -EINVAL;
749*4882a593Smuzhiyun 	}
750*4882a593Smuzhiyun 
751*4882a593Smuzhiyun 	/* Clear all scheme fields because the scheme may have been
752*4882a593Smuzhiyun 	 * previously used
753*4882a593Smuzhiyun 	 */
754*4882a593Smuzhiyun 	memset(scheme, 0, sizeof(struct keygen_scheme));
755*4882a593Smuzhiyun 
756*4882a593Smuzhiyun 	/* Setup scheme: */
757*4882a593Smuzhiyun 	scheme->hw_port_id = hw_port_id;
758*4882a593Smuzhiyun 	scheme->use_hashing = true;
759*4882a593Smuzhiyun 	scheme->base_fqid = hash_base_fqid;
760*4882a593Smuzhiyun 	scheme->hash_fqid_count = hash_size;
761*4882a593Smuzhiyun 	scheme->symmetric_hash = DEFAULT_SYMMETRIC_HASH;
762*4882a593Smuzhiyun 	scheme->hashShift = DEFAULT_HASH_SHIFT;
763*4882a593Smuzhiyun 
764*4882a593Smuzhiyun 	/* All Schemes in hard-coded configuration
765*4882a593Smuzhiyun 	 * are Indirect Schemes
766*4882a593Smuzhiyun 	 */
767*4882a593Smuzhiyun 	scheme->match_vector = 0;
768*4882a593Smuzhiyun 
769*4882a593Smuzhiyun 	err = keygen_scheme_setup(keygen, scheme_id, true);
770*4882a593Smuzhiyun 	if (err != 0) {
771*4882a593Smuzhiyun 		pr_err("Scheme setup failed\n");
772*4882a593Smuzhiyun 		return err;
773*4882a593Smuzhiyun 	}
774*4882a593Smuzhiyun 
775*4882a593Smuzhiyun 	/* Bind Rx port to Scheme */
776*4882a593Smuzhiyun 	err = keygen_bind_port_to_schemes(keygen, scheme_id, true);
777*4882a593Smuzhiyun 	if (err != 0) {
778*4882a593Smuzhiyun 		pr_err("Binding port to schemes failed\n");
779*4882a593Smuzhiyun 		return err;
780*4882a593Smuzhiyun 	}
781*4882a593Smuzhiyun 
782*4882a593Smuzhiyun 	return 0;
783*4882a593Smuzhiyun }
784*4882a593Smuzhiyun EXPORT_SYMBOL(keygen_port_hashing_init);
785